11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux
31da177e4SLinus Torvalds Copyright (C) 2000-2001 Qualcomm Incorporated
4590051deSGustavo F. Padovan Copyright (C) 2011 ProFUSION Embedded Systems
51da177e4SLinus Torvalds
61da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify
91da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as
101da177e4SLinus Torvalds published by the Free Software Foundation;
111da177e4SLinus Torvalds
121da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
131da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
141da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
151da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
161da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
171da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
181da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
191da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
201da177e4SLinus Torvalds
211da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
221da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
231da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED.
241da177e4SLinus Torvalds */
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds /* Bluetooth HCI core. */
271da177e4SLinus Torvalds
288c520a59SGustavo Padovan #include <linux/export.h>
29611b30f7SMarcel Holtmann #include <linux/rfkill.h>
30baf27f6eSMarcel Holtmann #include <linux/debugfs.h>
3199780a7bSJohan Hedberg #include <linux/crypto.h>
329f30de9eSTamas Koczka #include <linux/kcov.h>
337a0e5b15SMatthias Kaehlcke #include <linux/property.h>
349952d90eSAbhishek Pandit-Subedi #include <linux/suspend.h>
359952d90eSAbhishek Pandit-Subedi #include <linux/wait.h>
3647219839SMarcel Holtmann #include <asm/unaligned.h>
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h>
391da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h>
404bc58f51SJohan Hedberg #include <net/bluetooth/l2cap.h>
41af58925cSMarcel Holtmann #include <net/bluetooth/mgmt.h>
421da177e4SLinus Torvalds
430857dd3bSJohan Hedberg #include "hci_request.h"
4460c5f5fbSMarcel Holtmann #include "hci_debugfs.h"
45970c4e46SJohan Hedberg #include "smp.h"
466d5d2ee6SHeiner Kallweit #include "leds.h"
47145373cbSMiao-chen Chou #include "msft.h"
48f67743f9SMarcel Holtmann #include "aosp.h"
498961987fSKiran K #include "hci_codec.h"
50970c4e46SJohan Hedberg
51b78752ccSMarcel Holtmann static void hci_rx_work(struct work_struct *work);
52c347b765SGustavo F. Padovan static void hci_cmd_work(struct work_struct *work);
533eff45eaSGustavo F. Padovan static void hci_tx_work(struct work_struct *work);
541da177e4SLinus Torvalds
551da177e4SLinus Torvalds /* HCI device list */
561da177e4SLinus Torvalds LIST_HEAD(hci_dev_list);
571da177e4SLinus Torvalds DEFINE_RWLOCK(hci_dev_list_lock);
581da177e4SLinus Torvalds
591da177e4SLinus Torvalds /* HCI callback list */
601da177e4SLinus Torvalds LIST_HEAD(hci_cb_list);
61fba7ecf0SJohan Hedberg DEFINE_MUTEX(hci_cb_list_lock);
621da177e4SLinus Torvalds
633df92b31SSasha Levin /* HCI ID Numbering */
643df92b31SSasha Levin static DEFINE_IDA(hci_index_ida);
653df92b31SSasha Levin
hci_scan_req(struct hci_request * req,unsigned long opt)66a1d01db1SJohan Hedberg static int hci_scan_req(struct hci_request *req, unsigned long opt)
671da177e4SLinus Torvalds {
681da177e4SLinus Torvalds __u8 scan = opt;
691da177e4SLinus Torvalds
7042c6b129SJohan Hedberg BT_DBG("%s %x", req->hdev->name, scan);
711da177e4SLinus Torvalds
721da177e4SLinus Torvalds /* Inquiry and Page scans */
7342c6b129SJohan Hedberg hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
74a1d01db1SJohan Hedberg return 0;
751da177e4SLinus Torvalds }
761da177e4SLinus Torvalds
hci_auth_req(struct hci_request * req,unsigned long opt)77a1d01db1SJohan Hedberg static int hci_auth_req(struct hci_request *req, unsigned long opt)
781da177e4SLinus Torvalds {
791da177e4SLinus Torvalds __u8 auth = opt;
801da177e4SLinus Torvalds
8142c6b129SJohan Hedberg BT_DBG("%s %x", req->hdev->name, auth);
821da177e4SLinus Torvalds
831da177e4SLinus Torvalds /* Authentication */
8442c6b129SJohan Hedberg hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth);
85a1d01db1SJohan Hedberg return 0;
861da177e4SLinus Torvalds }
871da177e4SLinus Torvalds
hci_encrypt_req(struct hci_request * req,unsigned long opt)88a1d01db1SJohan Hedberg static int hci_encrypt_req(struct hci_request *req, unsigned long opt)
891da177e4SLinus Torvalds {
901da177e4SLinus Torvalds __u8 encrypt = opt;
911da177e4SLinus Torvalds
9242c6b129SJohan Hedberg BT_DBG("%s %x", req->hdev->name, encrypt);
931da177e4SLinus Torvalds
94e4e8e37cSMarcel Holtmann /* Encryption */
9542c6b129SJohan Hedberg hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt);
96a1d01db1SJohan Hedberg return 0;
971da177e4SLinus Torvalds }
981da177e4SLinus Torvalds
hci_linkpol_req(struct hci_request * req,unsigned long opt)99a1d01db1SJohan Hedberg static int hci_linkpol_req(struct hci_request *req, unsigned long opt)
100e4e8e37cSMarcel Holtmann {
101e4e8e37cSMarcel Holtmann __le16 policy = cpu_to_le16(opt);
102e4e8e37cSMarcel Holtmann
10342c6b129SJohan Hedberg BT_DBG("%s %x", req->hdev->name, policy);
104e4e8e37cSMarcel Holtmann
105e4e8e37cSMarcel Holtmann /* Default link policy */
10642c6b129SJohan Hedberg hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy);
107a1d01db1SJohan Hedberg return 0;
108e4e8e37cSMarcel Holtmann }
109e4e8e37cSMarcel Holtmann
1101da177e4SLinus Torvalds /* Get HCI device by index.
1111da177e4SLinus Torvalds * Device is held on return. */
hci_dev_get(int index)1121da177e4SLinus Torvalds struct hci_dev *hci_dev_get(int index)
1131da177e4SLinus Torvalds {
1148035ded4SLuiz Augusto von Dentz struct hci_dev *hdev = NULL, *d;
1151da177e4SLinus Torvalds
1161da177e4SLinus Torvalds BT_DBG("%d", index);
1171da177e4SLinus Torvalds
1181da177e4SLinus Torvalds if (index < 0)
1191da177e4SLinus Torvalds return NULL;
1201da177e4SLinus Torvalds
1211da177e4SLinus Torvalds read_lock(&hci_dev_list_lock);
1228035ded4SLuiz Augusto von Dentz list_for_each_entry(d, &hci_dev_list, list) {
1231da177e4SLinus Torvalds if (d->id == index) {
1241da177e4SLinus Torvalds hdev = hci_dev_hold(d);
1251da177e4SLinus Torvalds break;
1261da177e4SLinus Torvalds }
1271da177e4SLinus Torvalds }
1281da177e4SLinus Torvalds read_unlock(&hci_dev_list_lock);
1291da177e4SLinus Torvalds return hdev;
1301da177e4SLinus Torvalds }
1311da177e4SLinus Torvalds
1321da177e4SLinus Torvalds /* ---- Inquiry support ---- */
133ff9ef578SJohan Hedberg
hci_discovery_active(struct hci_dev * hdev)13430dc78e1SJohan Hedberg bool hci_discovery_active(struct hci_dev *hdev)
13530dc78e1SJohan Hedberg {
13630dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery;
13730dc78e1SJohan Hedberg
1386fbe195dSAndre Guedes switch (discov->state) {
139343f935bSAndre Guedes case DISCOVERY_FINDING:
1406fbe195dSAndre Guedes case DISCOVERY_RESOLVING:
14130dc78e1SJohan Hedberg return true;
14230dc78e1SJohan Hedberg
1436fbe195dSAndre Guedes default:
14430dc78e1SJohan Hedberg return false;
14530dc78e1SJohan Hedberg }
1466fbe195dSAndre Guedes }
14730dc78e1SJohan Hedberg
hci_discovery_set_state(struct hci_dev * hdev,int state)148ff9ef578SJohan Hedberg void hci_discovery_set_state(struct hci_dev *hdev, int state)
149ff9ef578SJohan Hedberg {
150bb3e0a33SJohan Hedberg int old_state = hdev->discovery.state;
151bb3e0a33SJohan Hedberg
152ff9ef578SJohan Hedberg BT_DBG("%s state %u -> %u", hdev->name, hdev->discovery.state, state);
153ff9ef578SJohan Hedberg
154bb3e0a33SJohan Hedberg if (old_state == state)
155ff9ef578SJohan Hedberg return;
156ff9ef578SJohan Hedberg
157bb3e0a33SJohan Hedberg hdev->discovery.state = state;
158bb3e0a33SJohan Hedberg
159ff9ef578SJohan Hedberg switch (state) {
160ff9ef578SJohan Hedberg case DISCOVERY_STOPPED:
1615bee2fd6SLuiz Augusto von Dentz hci_update_passive_scan(hdev);
162c54c3860SAndre Guedes
163bb3e0a33SJohan Hedberg if (old_state != DISCOVERY_STARTING)
164ff9ef578SJohan Hedberg mgmt_discovering(hdev, 0);
165ff9ef578SJohan Hedberg break;
166ff9ef578SJohan Hedberg case DISCOVERY_STARTING:
167ff9ef578SJohan Hedberg break;
168343f935bSAndre Guedes case DISCOVERY_FINDING:
169ff9ef578SJohan Hedberg mgmt_discovering(hdev, 1);
170ff9ef578SJohan Hedberg break;
17130dc78e1SJohan Hedberg case DISCOVERY_RESOLVING:
17230dc78e1SJohan Hedberg break;
173ff9ef578SJohan Hedberg case DISCOVERY_STOPPING:
174ff9ef578SJohan Hedberg break;
175ff9ef578SJohan Hedberg }
176ff9ef578SJohan Hedberg }
177ff9ef578SJohan Hedberg
hci_inquiry_cache_flush(struct hci_dev * hdev)1781f9b9a5dSAndre Guedes void hci_inquiry_cache_flush(struct hci_dev *hdev)
1791da177e4SLinus Torvalds {
18030883512SJohan Hedberg struct discovery_state *cache = &hdev->discovery;
181b57c1a56SJohan Hedberg struct inquiry_entry *p, *n;
1821da177e4SLinus Torvalds
183561aafbcSJohan Hedberg list_for_each_entry_safe(p, n, &cache->all, all) {
184561aafbcSJohan Hedberg list_del(&p->all);
185b57c1a56SJohan Hedberg kfree(p);
1861da177e4SLinus Torvalds }
187561aafbcSJohan Hedberg
188561aafbcSJohan Hedberg INIT_LIST_HEAD(&cache->unknown);
189561aafbcSJohan Hedberg INIT_LIST_HEAD(&cache->resolve);
1901da177e4SLinus Torvalds }
1911da177e4SLinus Torvalds
hci_inquiry_cache_lookup(struct hci_dev * hdev,bdaddr_t * bdaddr)192a8c5fb1aSGustavo Padovan struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
193a8c5fb1aSGustavo Padovan bdaddr_t *bdaddr)
1941da177e4SLinus Torvalds {
19530883512SJohan Hedberg struct discovery_state *cache = &hdev->discovery;
1961da177e4SLinus Torvalds struct inquiry_entry *e;
1971da177e4SLinus Torvalds
1986ed93dc6SAndrei Emeltchenko BT_DBG("cache %p, %pMR", cache, bdaddr);
1991da177e4SLinus Torvalds
200561aafbcSJohan Hedberg list_for_each_entry(e, &cache->all, all) {
2011da177e4SLinus Torvalds if (!bacmp(&e->data.bdaddr, bdaddr))
2021da177e4SLinus Torvalds return e;
2031da177e4SLinus Torvalds }
2041da177e4SLinus Torvalds
205b57c1a56SJohan Hedberg return NULL;
206b57c1a56SJohan Hedberg }
207b57c1a56SJohan Hedberg
hci_inquiry_cache_lookup_unknown(struct hci_dev * hdev,bdaddr_t * bdaddr)208561aafbcSJohan Hedberg struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
209561aafbcSJohan Hedberg bdaddr_t *bdaddr)
210561aafbcSJohan Hedberg {
21130883512SJohan Hedberg struct discovery_state *cache = &hdev->discovery;
212561aafbcSJohan Hedberg struct inquiry_entry *e;
213561aafbcSJohan Hedberg
2146ed93dc6SAndrei Emeltchenko BT_DBG("cache %p, %pMR", cache, bdaddr);
215561aafbcSJohan Hedberg
216561aafbcSJohan Hedberg list_for_each_entry(e, &cache->unknown, list) {
217561aafbcSJohan Hedberg if (!bacmp(&e->data.bdaddr, bdaddr))
218561aafbcSJohan Hedberg return e;
219561aafbcSJohan Hedberg }
220561aafbcSJohan Hedberg
221561aafbcSJohan Hedberg return NULL;
222561aafbcSJohan Hedberg }
223561aafbcSJohan Hedberg
hci_inquiry_cache_lookup_resolve(struct hci_dev * hdev,bdaddr_t * bdaddr,int state)22430dc78e1SJohan Hedberg struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
22530dc78e1SJohan Hedberg bdaddr_t *bdaddr,
22630dc78e1SJohan Hedberg int state)
22730dc78e1SJohan Hedberg {
22830dc78e1SJohan Hedberg struct discovery_state *cache = &hdev->discovery;
22930dc78e1SJohan Hedberg struct inquiry_entry *e;
23030dc78e1SJohan Hedberg
2316ed93dc6SAndrei Emeltchenko BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state);
23230dc78e1SJohan Hedberg
23330dc78e1SJohan Hedberg list_for_each_entry(e, &cache->resolve, list) {
23430dc78e1SJohan Hedberg if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state)
23530dc78e1SJohan Hedberg return e;
23630dc78e1SJohan Hedberg if (!bacmp(&e->data.bdaddr, bdaddr))
23730dc78e1SJohan Hedberg return e;
23830dc78e1SJohan Hedberg }
23930dc78e1SJohan Hedberg
24030dc78e1SJohan Hedberg return NULL;
24130dc78e1SJohan Hedberg }
24230dc78e1SJohan Hedberg
hci_inquiry_cache_update_resolve(struct hci_dev * hdev,struct inquiry_entry * ie)243a3d4e20aSJohan Hedberg void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
244a3d4e20aSJohan Hedberg struct inquiry_entry *ie)
245a3d4e20aSJohan Hedberg {
246a3d4e20aSJohan Hedberg struct discovery_state *cache = &hdev->discovery;
247a3d4e20aSJohan Hedberg struct list_head *pos = &cache->resolve;
248a3d4e20aSJohan Hedberg struct inquiry_entry *p;
249a3d4e20aSJohan Hedberg
250a3d4e20aSJohan Hedberg list_del(&ie->list);
251a3d4e20aSJohan Hedberg
252a3d4e20aSJohan Hedberg list_for_each_entry(p, &cache->resolve, list) {
253a3d4e20aSJohan Hedberg if (p->name_state != NAME_PENDING &&
254a3d4e20aSJohan Hedberg abs(p->data.rssi) >= abs(ie->data.rssi))
255a3d4e20aSJohan Hedberg break;
256a3d4e20aSJohan Hedberg pos = &p->list;
257a3d4e20aSJohan Hedberg }
258a3d4e20aSJohan Hedberg
259a3d4e20aSJohan Hedberg list_add(&ie->list, pos);
260a3d4e20aSJohan Hedberg }
261a3d4e20aSJohan Hedberg
hci_inquiry_cache_update(struct hci_dev * hdev,struct inquiry_data * data,bool name_known)262af58925cSMarcel Holtmann u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
263af58925cSMarcel Holtmann bool name_known)
2641da177e4SLinus Torvalds {
26530883512SJohan Hedberg struct discovery_state *cache = &hdev->discovery;
26670f23020SAndrei Emeltchenko struct inquiry_entry *ie;
267af58925cSMarcel Holtmann u32 flags = 0;
2681da177e4SLinus Torvalds
2696ed93dc6SAndrei Emeltchenko BT_DBG("cache %p, %pMR", cache, &data->bdaddr);
2701da177e4SLinus Torvalds
2716928a924SJohan Hedberg hci_remove_remote_oob_data(hdev, &data->bdaddr, BDADDR_BREDR);
2722b2fec4dSSzymon Janc
273af58925cSMarcel Holtmann if (!data->ssp_mode)
274af58925cSMarcel Holtmann flags |= MGMT_DEV_FOUND_LEGACY_PAIRING;
275388fc8faSJohan Hedberg
27670f23020SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr);
277a3d4e20aSJohan Hedberg if (ie) {
278af58925cSMarcel Holtmann if (!ie->data.ssp_mode)
279af58925cSMarcel Holtmann flags |= MGMT_DEV_FOUND_LEGACY_PAIRING;
280388fc8faSJohan Hedberg
281a3d4e20aSJohan Hedberg if (ie->name_state == NAME_NEEDED &&
282a3d4e20aSJohan Hedberg data->rssi != ie->data.rssi) {
283a3d4e20aSJohan Hedberg ie->data.rssi = data->rssi;
284a3d4e20aSJohan Hedberg hci_inquiry_cache_update_resolve(hdev, ie);
285a3d4e20aSJohan Hedberg }
286a3d4e20aSJohan Hedberg
287561aafbcSJohan Hedberg goto update;
288a3d4e20aSJohan Hedberg }
289561aafbcSJohan Hedberg
2901da177e4SLinus Torvalds /* Entry not in the cache. Add new one. */
29127f70f3eSJohan Hedberg ie = kzalloc(sizeof(*ie), GFP_KERNEL);
292af58925cSMarcel Holtmann if (!ie) {
293af58925cSMarcel Holtmann flags |= MGMT_DEV_FOUND_CONFIRM_NAME;
294af58925cSMarcel Holtmann goto done;
295af58925cSMarcel Holtmann }
29670f23020SAndrei Emeltchenko
297561aafbcSJohan Hedberg list_add(&ie->all, &cache->all);
298561aafbcSJohan Hedberg
299561aafbcSJohan Hedberg if (name_known) {
300561aafbcSJohan Hedberg ie->name_state = NAME_KNOWN;
301561aafbcSJohan Hedberg } else {
302561aafbcSJohan Hedberg ie->name_state = NAME_NOT_KNOWN;
303561aafbcSJohan Hedberg list_add(&ie->list, &cache->unknown);
304561aafbcSJohan Hedberg }
305561aafbcSJohan Hedberg
306561aafbcSJohan Hedberg update:
307561aafbcSJohan Hedberg if (name_known && ie->name_state != NAME_KNOWN &&
308561aafbcSJohan Hedberg ie->name_state != NAME_PENDING) {
309561aafbcSJohan Hedberg ie->name_state = NAME_KNOWN;
310561aafbcSJohan Hedberg list_del(&ie->list);
3111da177e4SLinus Torvalds }
3121da177e4SLinus Torvalds
31370f23020SAndrei Emeltchenko memcpy(&ie->data, data, sizeof(*data));
31470f23020SAndrei Emeltchenko ie->timestamp = jiffies;
3151da177e4SLinus Torvalds cache->timestamp = jiffies;
3163175405bSJohan Hedberg
3173175405bSJohan Hedberg if (ie->name_state == NAME_NOT_KNOWN)
318af58925cSMarcel Holtmann flags |= MGMT_DEV_FOUND_CONFIRM_NAME;
3193175405bSJohan Hedberg
320af58925cSMarcel Holtmann done:
321af58925cSMarcel Holtmann return flags;
3221da177e4SLinus Torvalds }
3231da177e4SLinus Torvalds
inquiry_cache_dump(struct hci_dev * hdev,int num,__u8 * buf)3241da177e4SLinus Torvalds static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf)
3251da177e4SLinus Torvalds {
32630883512SJohan Hedberg struct discovery_state *cache = &hdev->discovery;
3271da177e4SLinus Torvalds struct inquiry_info *info = (struct inquiry_info *) buf;
3281da177e4SLinus Torvalds struct inquiry_entry *e;
3291da177e4SLinus Torvalds int copied = 0;
3301da177e4SLinus Torvalds
331561aafbcSJohan Hedberg list_for_each_entry(e, &cache->all, all) {
3321da177e4SLinus Torvalds struct inquiry_data *data = &e->data;
333b57c1a56SJohan Hedberg
334b57c1a56SJohan Hedberg if (copied >= num)
335b57c1a56SJohan Hedberg break;
336b57c1a56SJohan Hedberg
3371da177e4SLinus Torvalds bacpy(&info->bdaddr, &data->bdaddr);
3381da177e4SLinus Torvalds info->pscan_rep_mode = data->pscan_rep_mode;
3391da177e4SLinus Torvalds info->pscan_period_mode = data->pscan_period_mode;
3401da177e4SLinus Torvalds info->pscan_mode = data->pscan_mode;
3411da177e4SLinus Torvalds memcpy(info->dev_class, data->dev_class, 3);
3421da177e4SLinus Torvalds info->clock_offset = data->clock_offset;
343b57c1a56SJohan Hedberg
3441da177e4SLinus Torvalds info++;
345b57c1a56SJohan Hedberg copied++;
3461da177e4SLinus Torvalds }
3471da177e4SLinus Torvalds
3481da177e4SLinus Torvalds BT_DBG("cache %p, copied %d", cache, copied);
3491da177e4SLinus Torvalds return copied;
3501da177e4SLinus Torvalds }
3511da177e4SLinus Torvalds
hci_inq_req(struct hci_request * req,unsigned long opt)352a1d01db1SJohan Hedberg static int hci_inq_req(struct hci_request *req, unsigned long opt)
3531da177e4SLinus Torvalds {
3541da177e4SLinus Torvalds struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt;
35542c6b129SJohan Hedberg struct hci_dev *hdev = req->hdev;
3561da177e4SLinus Torvalds struct hci_cp_inquiry cp;
3571da177e4SLinus Torvalds
3581da177e4SLinus Torvalds BT_DBG("%s", hdev->name);
3591da177e4SLinus Torvalds
3601da177e4SLinus Torvalds if (test_bit(HCI_INQUIRY, &hdev->flags))
361a1d01db1SJohan Hedberg return 0;
3621da177e4SLinus Torvalds
3631da177e4SLinus Torvalds /* Start Inquiry */
3641da177e4SLinus Torvalds memcpy(&cp.lap, &ir->lap, 3);
3651da177e4SLinus Torvalds cp.length = ir->length;
3661da177e4SLinus Torvalds cp.num_rsp = ir->num_rsp;
36742c6b129SJohan Hedberg hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
368a1d01db1SJohan Hedberg
369a1d01db1SJohan Hedberg return 0;
3701da177e4SLinus Torvalds }
3711da177e4SLinus Torvalds
hci_inquiry(void __user * arg)3721da177e4SLinus Torvalds int hci_inquiry(void __user *arg)
3731da177e4SLinus Torvalds {
3741da177e4SLinus Torvalds __u8 __user *ptr = arg;
3751da177e4SLinus Torvalds struct hci_inquiry_req ir;
3761da177e4SLinus Torvalds struct hci_dev *hdev;
3771da177e4SLinus Torvalds int err = 0, do_inquiry = 0, max_rsp;
3781da177e4SLinus Torvalds long timeo;
3791da177e4SLinus Torvalds __u8 *buf;
3801da177e4SLinus Torvalds
3811da177e4SLinus Torvalds if (copy_from_user(&ir, ptr, sizeof(ir)))
3821da177e4SLinus Torvalds return -EFAULT;
3831da177e4SLinus Torvalds
3845a08ecceSAndrei Emeltchenko hdev = hci_dev_get(ir.dev_id);
3855a08ecceSAndrei Emeltchenko if (!hdev)
3861da177e4SLinus Torvalds return -ENODEV;
3871da177e4SLinus Torvalds
388d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
3890736cfa8SMarcel Holtmann err = -EBUSY;
3900736cfa8SMarcel Holtmann goto done;
3910736cfa8SMarcel Holtmann }
3920736cfa8SMarcel Holtmann
393d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
394fee746b0SMarcel Holtmann err = -EOPNOTSUPP;
395fee746b0SMarcel Holtmann goto done;
396fee746b0SMarcel Holtmann }
397fee746b0SMarcel Holtmann
398d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
39956f87901SJohan Hedberg err = -EOPNOTSUPP;
40056f87901SJohan Hedberg goto done;
40156f87901SJohan Hedberg }
40256f87901SJohan Hedberg
403f41a4b2bSPavel Skripkin /* Restrict maximum inquiry length to 60 seconds */
404f41a4b2bSPavel Skripkin if (ir.length > 60) {
405f41a4b2bSPavel Skripkin err = -EINVAL;
406f41a4b2bSPavel Skripkin goto done;
407f41a4b2bSPavel Skripkin }
408f41a4b2bSPavel Skripkin
40909fd0de5SGustavo F. Padovan hci_dev_lock(hdev);
4101da177e4SLinus Torvalds if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
411a8c5fb1aSGustavo Padovan inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) {
4121f9b9a5dSAndre Guedes hci_inquiry_cache_flush(hdev);
4131da177e4SLinus Torvalds do_inquiry = 1;
4141da177e4SLinus Torvalds }
41509fd0de5SGustavo F. Padovan hci_dev_unlock(hdev);
4161da177e4SLinus Torvalds
41704837f64SMarcel Holtmann timeo = ir.length * msecs_to_jiffies(2000);
41870f23020SAndrei Emeltchenko
41970f23020SAndrei Emeltchenko if (do_inquiry) {
42001178cd4SJohan Hedberg err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir,
4214ebeee2dSJohan Hedberg timeo, NULL);
42270f23020SAndrei Emeltchenko if (err < 0)
4231da177e4SLinus Torvalds goto done;
4243e13fa1eSAndre Guedes
4253e13fa1eSAndre Guedes /* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is
4263e13fa1eSAndre Guedes * cleared). If it is interrupted by a signal, return -EINTR.
4273e13fa1eSAndre Guedes */
42874316201SNeilBrown if (wait_on_bit(&hdev->flags, HCI_INQUIRY,
42928a758c8SPan Bian TASK_INTERRUPTIBLE)) {
43028a758c8SPan Bian err = -EINTR;
43128a758c8SPan Bian goto done;
43228a758c8SPan Bian }
43370f23020SAndrei Emeltchenko }
4341da177e4SLinus Torvalds
4358fc9ced3SGustavo Padovan /* for unlimited number of responses we will use buffer with
4368fc9ced3SGustavo Padovan * 255 entries
4378fc9ced3SGustavo Padovan */
4381da177e4SLinus Torvalds max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp;
4391da177e4SLinus Torvalds
4401da177e4SLinus Torvalds /* cache_dump can't sleep. Therefore we allocate temp buffer and then
4411da177e4SLinus Torvalds * copy it to the user space.
4421da177e4SLinus Torvalds */
4436da2ec56SKees Cook buf = kmalloc_array(max_rsp, sizeof(struct inquiry_info), GFP_KERNEL);
44470f23020SAndrei Emeltchenko if (!buf) {
4451da177e4SLinus Torvalds err = -ENOMEM;
4461da177e4SLinus Torvalds goto done;
4471da177e4SLinus Torvalds }
4481da177e4SLinus Torvalds
44909fd0de5SGustavo F. Padovan hci_dev_lock(hdev);
4501da177e4SLinus Torvalds ir.num_rsp = inquiry_cache_dump(hdev, max_rsp, buf);
45109fd0de5SGustavo F. Padovan hci_dev_unlock(hdev);
4521da177e4SLinus Torvalds
4531da177e4SLinus Torvalds BT_DBG("num_rsp %d", ir.num_rsp);
4541da177e4SLinus Torvalds
4551da177e4SLinus Torvalds if (!copy_to_user(ptr, &ir, sizeof(ir))) {
4561da177e4SLinus Torvalds ptr += sizeof(ir);
4571da177e4SLinus Torvalds if (copy_to_user(ptr, buf, sizeof(struct inquiry_info) *
4581da177e4SLinus Torvalds ir.num_rsp))
4591da177e4SLinus Torvalds err = -EFAULT;
4601da177e4SLinus Torvalds } else
4611da177e4SLinus Torvalds err = -EFAULT;
4621da177e4SLinus Torvalds
4631da177e4SLinus Torvalds kfree(buf);
4641da177e4SLinus Torvalds
4651da177e4SLinus Torvalds done:
4661da177e4SLinus Torvalds hci_dev_put(hdev);
4671da177e4SLinus Torvalds return err;
4681da177e4SLinus Torvalds }
4691da177e4SLinus Torvalds
hci_dev_do_open(struct hci_dev * hdev)470cf75ad8bSLuiz Augusto von Dentz static int hci_dev_do_open(struct hci_dev *hdev)
471cf75ad8bSLuiz Augusto von Dentz {
472cf75ad8bSLuiz Augusto von Dentz int ret = 0;
473cf75ad8bSLuiz Augusto von Dentz
474cf75ad8bSLuiz Augusto von Dentz BT_DBG("%s %p", hdev->name, hdev);
475cf75ad8bSLuiz Augusto von Dentz
476cf75ad8bSLuiz Augusto von Dentz hci_req_sync_lock(hdev);
477cf75ad8bSLuiz Augusto von Dentz
478cf75ad8bSLuiz Augusto von Dentz ret = hci_dev_open_sync(hdev);
479cf75ad8bSLuiz Augusto von Dentz
480b504430cSJohan Hedberg hci_req_sync_unlock(hdev);
4811da177e4SLinus Torvalds return ret;
4821da177e4SLinus Torvalds }
4831da177e4SLinus Torvalds
484cbed0ca1SJohan Hedberg /* ---- HCI ioctl helpers ---- */
485cbed0ca1SJohan Hedberg
hci_dev_open(__u16 dev)486cbed0ca1SJohan Hedberg int hci_dev_open(__u16 dev)
487cbed0ca1SJohan Hedberg {
488cbed0ca1SJohan Hedberg struct hci_dev *hdev;
489cbed0ca1SJohan Hedberg int err;
490cbed0ca1SJohan Hedberg
491cbed0ca1SJohan Hedberg hdev = hci_dev_get(dev);
492cbed0ca1SJohan Hedberg if (!hdev)
493cbed0ca1SJohan Hedberg return -ENODEV;
494cbed0ca1SJohan Hedberg
4954a964404SMarcel Holtmann /* Devices that are marked as unconfigured can only be powered
496fee746b0SMarcel Holtmann * up as user channel. Trying to bring them up as normal devices
497fee746b0SMarcel Holtmann * will result into a failure. Only user channel operation is
498fee746b0SMarcel Holtmann * possible.
499fee746b0SMarcel Holtmann *
500fee746b0SMarcel Holtmann * When this function is called for a user channel, the flag
501fee746b0SMarcel Holtmann * HCI_USER_CHANNEL will be set first before attempting to
502fee746b0SMarcel Holtmann * open the device.
503fee746b0SMarcel Holtmann */
504d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
505d7a5a11dSMarcel Holtmann !hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
506fee746b0SMarcel Holtmann err = -EOPNOTSUPP;
507fee746b0SMarcel Holtmann goto done;
508fee746b0SMarcel Holtmann }
509fee746b0SMarcel Holtmann
510e1d08f40SJohan Hedberg /* We need to ensure that no other power on/off work is pending
511e1d08f40SJohan Hedberg * before proceeding to call hci_dev_do_open. This is
512e1d08f40SJohan Hedberg * particularly important if the setup procedure has not yet
513e1d08f40SJohan Hedberg * completed.
514e1d08f40SJohan Hedberg */
515a69d8927SMarcel Holtmann if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
516e1d08f40SJohan Hedberg cancel_delayed_work(&hdev->power_off);
517e1d08f40SJohan Hedberg
518a5c8f270SMarcel Holtmann /* After this call it is guaranteed that the setup procedure
519a5c8f270SMarcel Holtmann * has finished. This means that error conditions like RFKILL
520a5c8f270SMarcel Holtmann * or no valid public or static random address apply.
521a5c8f270SMarcel Holtmann */
522e1d08f40SJohan Hedberg flush_workqueue(hdev->req_workqueue);
523e1d08f40SJohan Hedberg
52412aa4f0aSMarcel Holtmann /* For controllers not using the management interface and that
525b6ae8457SJohan Hedberg * are brought up using legacy ioctl, set the HCI_BONDABLE bit
52612aa4f0aSMarcel Holtmann * so that pairing works for them. Once the management interface
52712aa4f0aSMarcel Holtmann * is in use this bit will be cleared again and userspace has
52812aa4f0aSMarcel Holtmann * to explicitly enable it.
52912aa4f0aSMarcel Holtmann */
530d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
531d7a5a11dSMarcel Holtmann !hci_dev_test_flag(hdev, HCI_MGMT))
532a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_BONDABLE);
53312aa4f0aSMarcel Holtmann
534cbed0ca1SJohan Hedberg err = hci_dev_do_open(hdev);
535cbed0ca1SJohan Hedberg
536fee746b0SMarcel Holtmann done:
537cbed0ca1SJohan Hedberg hci_dev_put(hdev);
538cbed0ca1SJohan Hedberg return err;
539cbed0ca1SJohan Hedberg }
540cbed0ca1SJohan Hedberg
hci_dev_do_close(struct hci_dev * hdev)541cf75ad8bSLuiz Augusto von Dentz int hci_dev_do_close(struct hci_dev *hdev)
542cf75ad8bSLuiz Augusto von Dentz {
543cf75ad8bSLuiz Augusto von Dentz int err;
544cf75ad8bSLuiz Augusto von Dentz
545cf75ad8bSLuiz Augusto von Dentz BT_DBG("%s %p", hdev->name, hdev);
546cf75ad8bSLuiz Augusto von Dentz
547cf75ad8bSLuiz Augusto von Dentz hci_req_sync_lock(hdev);
548cf75ad8bSLuiz Augusto von Dentz
549cf75ad8bSLuiz Augusto von Dentz err = hci_dev_close_sync(hdev);
550cf75ad8bSLuiz Augusto von Dentz
551b504430cSJohan Hedberg hci_req_sync_unlock(hdev);
5521da177e4SLinus Torvalds
55361969ef8SKangmin Park return err;
5541da177e4SLinus Torvalds }
5551da177e4SLinus Torvalds
hci_dev_close(__u16 dev)5561da177e4SLinus Torvalds int hci_dev_close(__u16 dev)
5571da177e4SLinus Torvalds {
5581da177e4SLinus Torvalds struct hci_dev *hdev;
5591da177e4SLinus Torvalds int err;
5601da177e4SLinus Torvalds
56170f23020SAndrei Emeltchenko hdev = hci_dev_get(dev);
56270f23020SAndrei Emeltchenko if (!hdev)
5631da177e4SLinus Torvalds return -ENODEV;
5648ee56540SMarcel Holtmann
565d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
5660736cfa8SMarcel Holtmann err = -EBUSY;
5670736cfa8SMarcel Holtmann goto done;
5680736cfa8SMarcel Holtmann }
5690736cfa8SMarcel Holtmann
570e36bea6eSVasyl Vavrychuk cancel_work_sync(&hdev->power_on);
571a69d8927SMarcel Holtmann if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
5728ee56540SMarcel Holtmann cancel_delayed_work(&hdev->power_off);
5738ee56540SMarcel Holtmann
5741da177e4SLinus Torvalds err = hci_dev_do_close(hdev);
5758ee56540SMarcel Holtmann
5760736cfa8SMarcel Holtmann done:
5771da177e4SLinus Torvalds hci_dev_put(hdev);
5781da177e4SLinus Torvalds return err;
5791da177e4SLinus Torvalds }
5801da177e4SLinus Torvalds
hci_dev_do_reset(struct hci_dev * hdev)5815c912495SMarcel Holtmann static int hci_dev_do_reset(struct hci_dev *hdev)
5821da177e4SLinus Torvalds {
5835c912495SMarcel Holtmann int ret;
5841da177e4SLinus Torvalds
5855c912495SMarcel Holtmann BT_DBG("%s %p", hdev->name, hdev);
5861da177e4SLinus Torvalds
587b504430cSJohan Hedberg hci_req_sync_lock(hdev);
5881da177e4SLinus Torvalds
5891da177e4SLinus Torvalds /* Drop queues */
5901da177e4SLinus Torvalds skb_queue_purge(&hdev->rx_q);
5911da177e4SLinus Torvalds skb_queue_purge(&hdev->cmd_q);
5921da177e4SLinus Torvalds
593877afadaSSchspa Shi /* Cancel these to avoid queueing non-chained pending work */
594877afadaSSchspa Shi hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
595deee93d1STetsuo Handa /* Wait for
596deee93d1STetsuo Handa *
597deee93d1STetsuo Handa * if (!hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE))
598deee93d1STetsuo Handa * queue_delayed_work(&hdev->{cmd,ncmd}_timer)
599deee93d1STetsuo Handa *
600deee93d1STetsuo Handa * inside RCU section to see the flag or complete scheduling.
601deee93d1STetsuo Handa */
602deee93d1STetsuo Handa synchronize_rcu();
603deee93d1STetsuo Handa /* Explicitly cancel works in case scheduled after setting the flag. */
604877afadaSSchspa Shi cancel_delayed_work(&hdev->cmd_timer);
605877afadaSSchspa Shi cancel_delayed_work(&hdev->ncmd_timer);
606877afadaSSchspa Shi
60776727c02SJohan Hedberg /* Avoid potential lockdep warnings from the *_flush() calls by
60876727c02SJohan Hedberg * ensuring the workqueue is empty up front.
60976727c02SJohan Hedberg */
61076727c02SJohan Hedberg drain_workqueue(hdev->workqueue);
61176727c02SJohan Hedberg
61209fd0de5SGustavo F. Padovan hci_dev_lock(hdev);
6131f9b9a5dSAndre Guedes hci_inquiry_cache_flush(hdev);
6141da177e4SLinus Torvalds hci_conn_hash_flush(hdev);
61509fd0de5SGustavo F. Padovan hci_dev_unlock(hdev);
6161da177e4SLinus Torvalds
6171da177e4SLinus Torvalds if (hdev->flush)
6181da177e4SLinus Torvalds hdev->flush(hdev);
6191da177e4SLinus Torvalds
620877afadaSSchspa Shi hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
621877afadaSSchspa Shi
6221da177e4SLinus Torvalds atomic_set(&hdev->cmd_cnt, 1);
62326afbd82SLuiz Augusto von Dentz hdev->acl_cnt = 0;
62426afbd82SLuiz Augusto von Dentz hdev->sco_cnt = 0;
62526afbd82SLuiz Augusto von Dentz hdev->le_cnt = 0;
62626afbd82SLuiz Augusto von Dentz hdev->iso_cnt = 0;
6271da177e4SLinus Torvalds
628d0b13706SLuiz Augusto von Dentz ret = hci_reset_sync(hdev);
6291da177e4SLinus Torvalds
630b504430cSJohan Hedberg hci_req_sync_unlock(hdev);
6311da177e4SLinus Torvalds return ret;
6321da177e4SLinus Torvalds }
6331da177e4SLinus Torvalds
hci_dev_reset(__u16 dev)6345c912495SMarcel Holtmann int hci_dev_reset(__u16 dev)
6355c912495SMarcel Holtmann {
6365c912495SMarcel Holtmann struct hci_dev *hdev;
6375c912495SMarcel Holtmann int err;
6385c912495SMarcel Holtmann
6395c912495SMarcel Holtmann hdev = hci_dev_get(dev);
6405c912495SMarcel Holtmann if (!hdev)
6415c912495SMarcel Holtmann return -ENODEV;
6425c912495SMarcel Holtmann
6435c912495SMarcel Holtmann if (!test_bit(HCI_UP, &hdev->flags)) {
6445c912495SMarcel Holtmann err = -ENETDOWN;
6455c912495SMarcel Holtmann goto done;
6465c912495SMarcel Holtmann }
6475c912495SMarcel Holtmann
648d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
6495c912495SMarcel Holtmann err = -EBUSY;
6505c912495SMarcel Holtmann goto done;
6515c912495SMarcel Holtmann }
6525c912495SMarcel Holtmann
653d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6545c912495SMarcel Holtmann err = -EOPNOTSUPP;
6555c912495SMarcel Holtmann goto done;
6565c912495SMarcel Holtmann }
6575c912495SMarcel Holtmann
6585c912495SMarcel Holtmann err = hci_dev_do_reset(hdev);
6595c912495SMarcel Holtmann
6605c912495SMarcel Holtmann done:
6615c912495SMarcel Holtmann hci_dev_put(hdev);
6625c912495SMarcel Holtmann return err;
6635c912495SMarcel Holtmann }
6645c912495SMarcel Holtmann
hci_dev_reset_stat(__u16 dev)6651da177e4SLinus Torvalds int hci_dev_reset_stat(__u16 dev)
6661da177e4SLinus Torvalds {
6671da177e4SLinus Torvalds struct hci_dev *hdev;
6681da177e4SLinus Torvalds int ret = 0;
6691da177e4SLinus Torvalds
67070f23020SAndrei Emeltchenko hdev = hci_dev_get(dev);
67170f23020SAndrei Emeltchenko if (!hdev)
6721da177e4SLinus Torvalds return -ENODEV;
6731da177e4SLinus Torvalds
674d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
6750736cfa8SMarcel Holtmann ret = -EBUSY;
6760736cfa8SMarcel Holtmann goto done;
6770736cfa8SMarcel Holtmann }
6780736cfa8SMarcel Holtmann
679d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
680fee746b0SMarcel Holtmann ret = -EOPNOTSUPP;
681fee746b0SMarcel Holtmann goto done;
682fee746b0SMarcel Holtmann }
683fee746b0SMarcel Holtmann
6841da177e4SLinus Torvalds memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
6851da177e4SLinus Torvalds
6860736cfa8SMarcel Holtmann done:
6871da177e4SLinus Torvalds hci_dev_put(hdev);
6881da177e4SLinus Torvalds return ret;
6891da177e4SLinus Torvalds }
6901da177e4SLinus Torvalds
hci_update_passive_scan_state(struct hci_dev * hdev,u8 scan)6915bee2fd6SLuiz Augusto von Dentz static void hci_update_passive_scan_state(struct hci_dev *hdev, u8 scan)
692123abc08SJohan Hedberg {
693bc6d2d04SJohan Hedberg bool conn_changed, discov_changed;
694123abc08SJohan Hedberg
695123abc08SJohan Hedberg BT_DBG("%s scan 0x%02x", hdev->name, scan);
696123abc08SJohan Hedberg
697123abc08SJohan Hedberg if ((scan & SCAN_PAGE))
698238be788SMarcel Holtmann conn_changed = !hci_dev_test_and_set_flag(hdev,
699238be788SMarcel Holtmann HCI_CONNECTABLE);
700123abc08SJohan Hedberg else
701a69d8927SMarcel Holtmann conn_changed = hci_dev_test_and_clear_flag(hdev,
702a69d8927SMarcel Holtmann HCI_CONNECTABLE);
703123abc08SJohan Hedberg
704bc6d2d04SJohan Hedberg if ((scan & SCAN_INQUIRY)) {
705238be788SMarcel Holtmann discov_changed = !hci_dev_test_and_set_flag(hdev,
706238be788SMarcel Holtmann HCI_DISCOVERABLE);
707bc6d2d04SJohan Hedberg } else {
708a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
709a69d8927SMarcel Holtmann discov_changed = hci_dev_test_and_clear_flag(hdev,
710a69d8927SMarcel Holtmann HCI_DISCOVERABLE);
711bc6d2d04SJohan Hedberg }
712bc6d2d04SJohan Hedberg
713d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_MGMT))
714123abc08SJohan Hedberg return;
715123abc08SJohan Hedberg
716bc6d2d04SJohan Hedberg if (conn_changed || discov_changed) {
717bc6d2d04SJohan Hedberg /* In case this was disabled through mgmt */
718a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
719bc6d2d04SJohan Hedberg
720d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
721651cd3d6SBrian Gix hci_update_adv_data(hdev, hdev->cur_adv_instance);
722bc6d2d04SJohan Hedberg
723123abc08SJohan Hedberg mgmt_new_settings(hdev);
724123abc08SJohan Hedberg }
725bc6d2d04SJohan Hedberg }
726123abc08SJohan Hedberg
hci_dev_cmd(unsigned int cmd,void __user * arg)7271da177e4SLinus Torvalds int hci_dev_cmd(unsigned int cmd, void __user *arg)
7281da177e4SLinus Torvalds {
7291da177e4SLinus Torvalds struct hci_dev *hdev;
7301da177e4SLinus Torvalds struct hci_dev_req dr;
7311da177e4SLinus Torvalds int err = 0;
7321da177e4SLinus Torvalds
7331da177e4SLinus Torvalds if (copy_from_user(&dr, arg, sizeof(dr)))
7341da177e4SLinus Torvalds return -EFAULT;
7351da177e4SLinus Torvalds
73670f23020SAndrei Emeltchenko hdev = hci_dev_get(dr.dev_id);
73770f23020SAndrei Emeltchenko if (!hdev)
7381da177e4SLinus Torvalds return -ENODEV;
7391da177e4SLinus Torvalds
740d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
7410736cfa8SMarcel Holtmann err = -EBUSY;
7420736cfa8SMarcel Holtmann goto done;
7430736cfa8SMarcel Holtmann }
7440736cfa8SMarcel Holtmann
745d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
746fee746b0SMarcel Holtmann err = -EOPNOTSUPP;
747fee746b0SMarcel Holtmann goto done;
748fee746b0SMarcel Holtmann }
749fee746b0SMarcel Holtmann
750d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
75156f87901SJohan Hedberg err = -EOPNOTSUPP;
75256f87901SJohan Hedberg goto done;
75356f87901SJohan Hedberg }
75456f87901SJohan Hedberg
7551da177e4SLinus Torvalds switch (cmd) {
7561da177e4SLinus Torvalds case HCISETAUTH:
75701178cd4SJohan Hedberg err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
7584ebeee2dSJohan Hedberg HCI_INIT_TIMEOUT, NULL);
7591da177e4SLinus Torvalds break;
7601da177e4SLinus Torvalds
7611da177e4SLinus Torvalds case HCISETENCRYPT:
7621da177e4SLinus Torvalds if (!lmp_encrypt_capable(hdev)) {
7631da177e4SLinus Torvalds err = -EOPNOTSUPP;
7641da177e4SLinus Torvalds break;
7651da177e4SLinus Torvalds }
7661da177e4SLinus Torvalds
7671da177e4SLinus Torvalds if (!test_bit(HCI_AUTH, &hdev->flags)) {
7681da177e4SLinus Torvalds /* Auth must be enabled first */
76901178cd4SJohan Hedberg err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
7704ebeee2dSJohan Hedberg HCI_INIT_TIMEOUT, NULL);
7711da177e4SLinus Torvalds if (err)
7721da177e4SLinus Torvalds break;
7731da177e4SLinus Torvalds }
7741da177e4SLinus Torvalds
77501178cd4SJohan Hedberg err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt,
7764ebeee2dSJohan Hedberg HCI_INIT_TIMEOUT, NULL);
7771da177e4SLinus Torvalds break;
7781da177e4SLinus Torvalds
7791da177e4SLinus Torvalds case HCISETSCAN:
78001178cd4SJohan Hedberg err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt,
7814ebeee2dSJohan Hedberg HCI_INIT_TIMEOUT, NULL);
78291a668b0SJohan Hedberg
783bc6d2d04SJohan Hedberg /* Ensure that the connectable and discoverable states
784bc6d2d04SJohan Hedberg * get correctly modified as this was a non-mgmt change.
78591a668b0SJohan Hedberg */
786123abc08SJohan Hedberg if (!err)
7875bee2fd6SLuiz Augusto von Dentz hci_update_passive_scan_state(hdev, dr.dev_opt);
7881da177e4SLinus Torvalds break;
7891da177e4SLinus Torvalds
7901da177e4SLinus Torvalds case HCISETLINKPOL:
79101178cd4SJohan Hedberg err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt,
7924ebeee2dSJohan Hedberg HCI_INIT_TIMEOUT, NULL);
7931da177e4SLinus Torvalds break;
7941da177e4SLinus Torvalds
7951da177e4SLinus Torvalds case HCISETLINKMODE:
796e4e8e37cSMarcel Holtmann hdev->link_mode = ((__u16) dr.dev_opt) &
797e4e8e37cSMarcel Holtmann (HCI_LM_MASTER | HCI_LM_ACCEPT);
798e4e8e37cSMarcel Holtmann break;
799e4e8e37cSMarcel Holtmann
800e4e8e37cSMarcel Holtmann case HCISETPTYPE:
801b7c23df8SJaganath Kanakkassery if (hdev->pkt_type == (__u16) dr.dev_opt)
802b7c23df8SJaganath Kanakkassery break;
803b7c23df8SJaganath Kanakkassery
804e4e8e37cSMarcel Holtmann hdev->pkt_type = (__u16) dr.dev_opt;
805b7c23df8SJaganath Kanakkassery mgmt_phy_configuration_changed(hdev, NULL);
8061da177e4SLinus Torvalds break;
8071da177e4SLinus Torvalds
8081da177e4SLinus Torvalds case HCISETACLMTU:
8091da177e4SLinus Torvalds hdev->acl_mtu = *((__u16 *) &dr.dev_opt + 1);
8101da177e4SLinus Torvalds hdev->acl_pkts = *((__u16 *) &dr.dev_opt + 0);
8111da177e4SLinus Torvalds break;
8121da177e4SLinus Torvalds
8131da177e4SLinus Torvalds case HCISETSCOMTU:
8141da177e4SLinus Torvalds hdev->sco_mtu = *((__u16 *) &dr.dev_opt + 1);
8151da177e4SLinus Torvalds hdev->sco_pkts = *((__u16 *) &dr.dev_opt + 0);
8161da177e4SLinus Torvalds break;
8171da177e4SLinus Torvalds
8181da177e4SLinus Torvalds default:
8191da177e4SLinus Torvalds err = -EINVAL;
8201da177e4SLinus Torvalds break;
8211da177e4SLinus Torvalds }
822e4e8e37cSMarcel Holtmann
8230736cfa8SMarcel Holtmann done:
8241da177e4SLinus Torvalds hci_dev_put(hdev);
8251da177e4SLinus Torvalds return err;
8261da177e4SLinus Torvalds }
8271da177e4SLinus Torvalds
hci_get_dev_list(void __user * arg)8281da177e4SLinus Torvalds int hci_get_dev_list(void __user *arg)
8291da177e4SLinus Torvalds {
8308035ded4SLuiz Augusto von Dentz struct hci_dev *hdev;
8311da177e4SLinus Torvalds struct hci_dev_list_req *dl;
8321da177e4SLinus Torvalds struct hci_dev_req *dr;
8331da177e4SLinus Torvalds int n = 0, size, err;
8341da177e4SLinus Torvalds __u16 dev_num;
8351da177e4SLinus Torvalds
8361da177e4SLinus Torvalds if (get_user(dev_num, (__u16 __user *) arg))
8371da177e4SLinus Torvalds return -EFAULT;
8381da177e4SLinus Torvalds
8391da177e4SLinus Torvalds if (!dev_num || dev_num > (PAGE_SIZE * 2) / sizeof(*dr))
8401da177e4SLinus Torvalds return -EINVAL;
8411da177e4SLinus Torvalds
8421da177e4SLinus Torvalds size = sizeof(*dl) + dev_num * sizeof(*dr);
8431da177e4SLinus Torvalds
84470f23020SAndrei Emeltchenko dl = kzalloc(size, GFP_KERNEL);
84570f23020SAndrei Emeltchenko if (!dl)
8461da177e4SLinus Torvalds return -ENOMEM;
8471da177e4SLinus Torvalds
8481da177e4SLinus Torvalds dr = dl->dev_req;
8491da177e4SLinus Torvalds
850f20d09d5SGustavo F. Padovan read_lock(&hci_dev_list_lock);
8518035ded4SLuiz Augusto von Dentz list_for_each_entry(hdev, &hci_dev_list, list) {
8522e84d8dbSMarcel Holtmann unsigned long flags = hdev->flags;
853c542a06cSJohan Hedberg
8542e84d8dbSMarcel Holtmann /* When the auto-off is configured it means the transport
8552e84d8dbSMarcel Holtmann * is running, but in that case still indicate that the
8562e84d8dbSMarcel Holtmann * device is actually down.
8572e84d8dbSMarcel Holtmann */
858d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_AUTO_OFF))
8592e84d8dbSMarcel Holtmann flags &= ~BIT(HCI_UP);
860c542a06cSJohan Hedberg
8611da177e4SLinus Torvalds (dr + n)->dev_id = hdev->id;
8622e84d8dbSMarcel Holtmann (dr + n)->dev_opt = flags;
863c542a06cSJohan Hedberg
8641da177e4SLinus Torvalds if (++n >= dev_num)
8651da177e4SLinus Torvalds break;
8661da177e4SLinus Torvalds }
867f20d09d5SGustavo F. Padovan read_unlock(&hci_dev_list_lock);
8681da177e4SLinus Torvalds
8691da177e4SLinus Torvalds dl->dev_num = n;
8701da177e4SLinus Torvalds size = sizeof(*dl) + n * sizeof(*dr);
8711da177e4SLinus Torvalds
8721da177e4SLinus Torvalds err = copy_to_user(arg, dl, size);
8731da177e4SLinus Torvalds kfree(dl);
8741da177e4SLinus Torvalds
8751da177e4SLinus Torvalds return err ? -EFAULT : 0;
8761da177e4SLinus Torvalds }
8771da177e4SLinus Torvalds
hci_get_dev_info(void __user * arg)8781da177e4SLinus Torvalds int hci_get_dev_info(void __user *arg)
8791da177e4SLinus Torvalds {
8801da177e4SLinus Torvalds struct hci_dev *hdev;
8811da177e4SLinus Torvalds struct hci_dev_info di;
8822e84d8dbSMarcel Holtmann unsigned long flags;
8831da177e4SLinus Torvalds int err = 0;
8841da177e4SLinus Torvalds
8851da177e4SLinus Torvalds if (copy_from_user(&di, arg, sizeof(di)))
8861da177e4SLinus Torvalds return -EFAULT;
8871da177e4SLinus Torvalds
88870f23020SAndrei Emeltchenko hdev = hci_dev_get(di.dev_id);
88970f23020SAndrei Emeltchenko if (!hdev)
8901da177e4SLinus Torvalds return -ENODEV;
8911da177e4SLinus Torvalds
8922e84d8dbSMarcel Holtmann /* When the auto-off is configured it means the transport
8932e84d8dbSMarcel Holtmann * is running, but in that case still indicate that the
8942e84d8dbSMarcel Holtmann * device is actually down.
8952e84d8dbSMarcel Holtmann */
896d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_AUTO_OFF))
8972e84d8dbSMarcel Holtmann flags = hdev->flags & ~BIT(HCI_UP);
8982e84d8dbSMarcel Holtmann else
8992e84d8dbSMarcel Holtmann flags = hdev->flags;
900c542a06cSJohan Hedberg
901a41c8efeSLuiz Augusto von Dentz strscpy(di.name, hdev->name, sizeof(di.name));
9021da177e4SLinus Torvalds di.bdaddr = hdev->bdaddr;
9035af2e235SLuiz Augusto von Dentz di.type = (hdev->bus & 0x0f);
9042e84d8dbSMarcel Holtmann di.flags = flags;
9051da177e4SLinus Torvalds di.pkt_type = hdev->pkt_type;
906572c7f84SJohan Hedberg if (lmp_bredr_capable(hdev)) {
9071da177e4SLinus Torvalds di.acl_mtu = hdev->acl_mtu;
9081da177e4SLinus Torvalds di.acl_pkts = hdev->acl_pkts;
9091da177e4SLinus Torvalds di.sco_mtu = hdev->sco_mtu;
9101da177e4SLinus Torvalds di.sco_pkts = hdev->sco_pkts;
911572c7f84SJohan Hedberg } else {
912572c7f84SJohan Hedberg di.acl_mtu = hdev->le_mtu;
913572c7f84SJohan Hedberg di.acl_pkts = hdev->le_pkts;
914572c7f84SJohan Hedberg di.sco_mtu = 0;
915572c7f84SJohan Hedberg di.sco_pkts = 0;
916572c7f84SJohan Hedberg }
9171da177e4SLinus Torvalds di.link_policy = hdev->link_policy;
9181da177e4SLinus Torvalds di.link_mode = hdev->link_mode;
9191da177e4SLinus Torvalds
9201da177e4SLinus Torvalds memcpy(&di.stat, &hdev->stat, sizeof(di.stat));
9211da177e4SLinus Torvalds memcpy(&di.features, &hdev->features, sizeof(di.features));
9221da177e4SLinus Torvalds
9231da177e4SLinus Torvalds if (copy_to_user(arg, &di, sizeof(di)))
9241da177e4SLinus Torvalds err = -EFAULT;
9251da177e4SLinus Torvalds
9261da177e4SLinus Torvalds hci_dev_put(hdev);
9271da177e4SLinus Torvalds
9281da177e4SLinus Torvalds return err;
9291da177e4SLinus Torvalds }
9301da177e4SLinus Torvalds
9311da177e4SLinus Torvalds /* ---- Interface to HCI drivers ---- */
9321da177e4SLinus Torvalds
hci_rfkill_set_block(void * data,bool blocked)933611b30f7SMarcel Holtmann static int hci_rfkill_set_block(void *data, bool blocked)
934611b30f7SMarcel Holtmann {
935611b30f7SMarcel Holtmann struct hci_dev *hdev = data;
936611b30f7SMarcel Holtmann
937611b30f7SMarcel Holtmann BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
938611b30f7SMarcel Holtmann
939d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
9400736cfa8SMarcel Holtmann return -EBUSY;
9410736cfa8SMarcel Holtmann
9425e130367SJohan Hedberg if (blocked) {
943a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_RFKILLED);
944d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
945d7a5a11dSMarcel Holtmann !hci_dev_test_flag(hdev, HCI_CONFIG))
946611b30f7SMarcel Holtmann hci_dev_do_close(hdev);
9475e130367SJohan Hedberg } else {
948a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_RFKILLED);
9495e130367SJohan Hedberg }
950611b30f7SMarcel Holtmann
951611b30f7SMarcel Holtmann return 0;
952611b30f7SMarcel Holtmann }
953611b30f7SMarcel Holtmann
954611b30f7SMarcel Holtmann static const struct rfkill_ops hci_rfkill_ops = {
955611b30f7SMarcel Holtmann .set_block = hci_rfkill_set_block,
956611b30f7SMarcel Holtmann };
957611b30f7SMarcel Holtmann
hci_power_on(struct work_struct * work)958ab81cbf9SJohan Hedberg static void hci_power_on(struct work_struct *work)
959ab81cbf9SJohan Hedberg {
960ab81cbf9SJohan Hedberg struct hci_dev *hdev = container_of(work, struct hci_dev, power_on);
96196570ffcSJohan Hedberg int err;
962ab81cbf9SJohan Hedberg
963ab81cbf9SJohan Hedberg BT_DBG("%s", hdev->name);
964ab81cbf9SJohan Hedberg
9652ff13894SJohan Hedberg if (test_bit(HCI_UP, &hdev->flags) &&
9662ff13894SJohan Hedberg hci_dev_test_flag(hdev, HCI_MGMT) &&
9672ff13894SJohan Hedberg hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
968d82142a8SWei-Ning Huang cancel_delayed_work(&hdev->power_off);
969cf75ad8bSLuiz Augusto von Dentz err = hci_powered_update_sync(hdev);
9702ff13894SJohan Hedberg mgmt_power_on(hdev, err);
9712ff13894SJohan Hedberg return;
9722ff13894SJohan Hedberg }
9732ff13894SJohan Hedberg
974cbed0ca1SJohan Hedberg err = hci_dev_do_open(hdev);
97596570ffcSJohan Hedberg if (err < 0) {
9763ad67582SJaganath Kanakkassery hci_dev_lock(hdev);
97796570ffcSJohan Hedberg mgmt_set_powered_failed(hdev, err);
9783ad67582SJaganath Kanakkassery hci_dev_unlock(hdev);
979ab81cbf9SJohan Hedberg return;
98096570ffcSJohan Hedberg }
981ab81cbf9SJohan Hedberg
982a5c8f270SMarcel Holtmann /* During the HCI setup phase, a few error conditions are
983a5c8f270SMarcel Holtmann * ignored and they need to be checked now. If they are still
984a5c8f270SMarcel Holtmann * valid, it is important to turn the device back off.
985a5c8f270SMarcel Holtmann */
986d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_RFKILLED) ||
987d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_UNCONFIGURED) ||
9885af2e235SLuiz Augusto von Dentz (!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
989a5c8f270SMarcel Holtmann !bacmp(&hdev->static_addr, BDADDR_ANY))) {
990a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_AUTO_OFF);
991bf543036SJohan Hedberg hci_dev_do_close(hdev);
992d7a5a11dSMarcel Holtmann } else if (hci_dev_test_flag(hdev, HCI_AUTO_OFF)) {
99319202573SJohan Hedberg queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
99419202573SJohan Hedberg HCI_AUTO_OFF_TIMEOUT);
995bf543036SJohan Hedberg }
996ab81cbf9SJohan Hedberg
997a69d8927SMarcel Holtmann if (hci_dev_test_and_clear_flag(hdev, HCI_SETUP)) {
9984a964404SMarcel Holtmann /* For unconfigured devices, set the HCI_RAW flag
9994a964404SMarcel Holtmann * so that userspace can easily identify them.
10004a964404SMarcel Holtmann */
1001d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
10024a964404SMarcel Holtmann set_bit(HCI_RAW, &hdev->flags);
10030602a8adSMarcel Holtmann
10040602a8adSMarcel Holtmann /* For fully configured devices, this will send
10050602a8adSMarcel Holtmann * the Index Added event. For unconfigured devices,
10060602a8adSMarcel Holtmann * it will send Unconfigued Index Added event.
10070602a8adSMarcel Holtmann *
10080602a8adSMarcel Holtmann * Devices with HCI_QUIRK_RAW_DEVICE are ignored
10090602a8adSMarcel Holtmann * and no event will be send.
10100602a8adSMarcel Holtmann */
1011744cf19eSJohan Hedberg mgmt_index_added(hdev);
1012a69d8927SMarcel Holtmann } else if (hci_dev_test_and_clear_flag(hdev, HCI_CONFIG)) {
10135ea234d3SMarcel Holtmann /* When the controller is now configured, then it
10145ea234d3SMarcel Holtmann * is important to clear the HCI_RAW flag.
10155ea234d3SMarcel Holtmann */
1016d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
10175ea234d3SMarcel Holtmann clear_bit(HCI_RAW, &hdev->flags);
10185ea234d3SMarcel Holtmann
1019d603b76bSMarcel Holtmann /* Powering on the controller with HCI_CONFIG set only
1020d603b76bSMarcel Holtmann * happens with the transition from unconfigured to
1021d603b76bSMarcel Holtmann * configured. This will send the Index Added event.
1022d603b76bSMarcel Holtmann */
1023d603b76bSMarcel Holtmann mgmt_index_added(hdev);
1024ab81cbf9SJohan Hedberg }
1025ab81cbf9SJohan Hedberg }
1026ab81cbf9SJohan Hedberg
hci_power_off(struct work_struct * work)1027ab81cbf9SJohan Hedberg static void hci_power_off(struct work_struct *work)
1028ab81cbf9SJohan Hedberg {
10293243553fSJohan Hedberg struct hci_dev *hdev = container_of(work, struct hci_dev,
10303243553fSJohan Hedberg power_off.work);
1031ab81cbf9SJohan Hedberg
1032ab81cbf9SJohan Hedberg BT_DBG("%s", hdev->name);
1033ab81cbf9SJohan Hedberg
10348ee56540SMarcel Holtmann hci_dev_do_close(hdev);
1035ab81cbf9SJohan Hedberg }
1036ab81cbf9SJohan Hedberg
hci_error_reset(struct work_struct * work)1037c7741d16SMarcel Holtmann static void hci_error_reset(struct work_struct *work)
1038c7741d16SMarcel Holtmann {
1039c7741d16SMarcel Holtmann struct hci_dev *hdev = container_of(work, struct hci_dev, error_reset);
1040c7741d16SMarcel Holtmann
10412ab9a19dSYing Hsu hci_dev_hold(hdev);
1042c7741d16SMarcel Holtmann BT_DBG("%s", hdev->name);
1043c7741d16SMarcel Holtmann
1044c7741d16SMarcel Holtmann if (hdev->hw_error)
1045c7741d16SMarcel Holtmann hdev->hw_error(hdev, hdev->hw_error_code);
1046c7741d16SMarcel Holtmann else
10472064ee33SMarcel Holtmann bt_dev_err(hdev, "hardware error 0x%2.2x", hdev->hw_error_code);
1048c7741d16SMarcel Holtmann
10492ab9a19dSYing Hsu if (!hci_dev_do_close(hdev))
1050c7741d16SMarcel Holtmann hci_dev_do_open(hdev);
10512ab9a19dSYing Hsu
10522ab9a19dSYing Hsu hci_dev_put(hdev);
1053c7741d16SMarcel Holtmann }
1054c7741d16SMarcel Holtmann
hci_uuids_clear(struct hci_dev * hdev)105535f7498aSJohan Hedberg void hci_uuids_clear(struct hci_dev *hdev)
10562aeb9a1aSJohan Hedberg {
10574821002cSJohan Hedberg struct bt_uuid *uuid, *tmp;
10582aeb9a1aSJohan Hedberg
10594821002cSJohan Hedberg list_for_each_entry_safe(uuid, tmp, &hdev->uuids, list) {
10604821002cSJohan Hedberg list_del(&uuid->list);
10612aeb9a1aSJohan Hedberg kfree(uuid);
10622aeb9a1aSJohan Hedberg }
10632aeb9a1aSJohan Hedberg }
10642aeb9a1aSJohan Hedberg
hci_link_keys_clear(struct hci_dev * hdev)106535f7498aSJohan Hedberg void hci_link_keys_clear(struct hci_dev *hdev)
106655ed8ca1SJohan Hedberg {
10673673952cSMin Li struct link_key *key, *tmp;
106855ed8ca1SJohan Hedberg
10693673952cSMin Li list_for_each_entry_safe(key, tmp, &hdev->link_keys, list) {
10700378b597SJohan Hedberg list_del_rcu(&key->list);
10710378b597SJohan Hedberg kfree_rcu(key, rcu);
107255ed8ca1SJohan Hedberg }
107355ed8ca1SJohan Hedberg }
107455ed8ca1SJohan Hedberg
hci_smp_ltks_clear(struct hci_dev * hdev)107535f7498aSJohan Hedberg void hci_smp_ltks_clear(struct hci_dev *hdev)
1076b899efafSVinicius Costa Gomes {
10773673952cSMin Li struct smp_ltk *k, *tmp;
1078b899efafSVinicius Costa Gomes
10793673952cSMin Li list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
1080970d0f1bSJohan Hedberg list_del_rcu(&k->list);
1081970d0f1bSJohan Hedberg kfree_rcu(k, rcu);
1082b899efafSVinicius Costa Gomes }
1083b899efafSVinicius Costa Gomes }
1084b899efafSVinicius Costa Gomes
hci_smp_irks_clear(struct hci_dev * hdev)1085970c4e46SJohan Hedberg void hci_smp_irks_clear(struct hci_dev *hdev)
1086970c4e46SJohan Hedberg {
10873673952cSMin Li struct smp_irk *k, *tmp;
1088970c4e46SJohan Hedberg
10893673952cSMin Li list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
1090adae20cbSJohan Hedberg list_del_rcu(&k->list);
1091adae20cbSJohan Hedberg kfree_rcu(k, rcu);
1092970c4e46SJohan Hedberg }
1093970c4e46SJohan Hedberg }
1094970c4e46SJohan Hedberg
hci_blocked_keys_clear(struct hci_dev * hdev)1095600a8749SAlain Michaud void hci_blocked_keys_clear(struct hci_dev *hdev)
1096600a8749SAlain Michaud {
10973673952cSMin Li struct blocked_key *b, *tmp;
1098600a8749SAlain Michaud
10993673952cSMin Li list_for_each_entry_safe(b, tmp, &hdev->blocked_keys, list) {
1100600a8749SAlain Michaud list_del_rcu(&b->list);
1101600a8749SAlain Michaud kfree_rcu(b, rcu);
1102600a8749SAlain Michaud }
1103600a8749SAlain Michaud }
1104600a8749SAlain Michaud
hci_is_blocked_key(struct hci_dev * hdev,u8 type,u8 val[16])1105600a8749SAlain Michaud bool hci_is_blocked_key(struct hci_dev *hdev, u8 type, u8 val[16])
1106600a8749SAlain Michaud {
1107600a8749SAlain Michaud bool blocked = false;
1108600a8749SAlain Michaud struct blocked_key *b;
1109600a8749SAlain Michaud
1110600a8749SAlain Michaud rcu_read_lock();
11110c2ac7d4SMadhuparna Bhowmik list_for_each_entry_rcu(b, &hdev->blocked_keys, list) {
1112600a8749SAlain Michaud if (b->type == type && !memcmp(b->val, val, sizeof(b->val))) {
1113600a8749SAlain Michaud blocked = true;
1114600a8749SAlain Michaud break;
1115600a8749SAlain Michaud }
1116600a8749SAlain Michaud }
1117600a8749SAlain Michaud
1118600a8749SAlain Michaud rcu_read_unlock();
1119600a8749SAlain Michaud return blocked;
1120600a8749SAlain Michaud }
1121600a8749SAlain Michaud
hci_find_link_key(struct hci_dev * hdev,bdaddr_t * bdaddr)112255ed8ca1SJohan Hedberg struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
112355ed8ca1SJohan Hedberg {
112455ed8ca1SJohan Hedberg struct link_key *k;
112555ed8ca1SJohan Hedberg
11260378b597SJohan Hedberg rcu_read_lock();
11270378b597SJohan Hedberg list_for_each_entry_rcu(k, &hdev->link_keys, list) {
11280378b597SJohan Hedberg if (bacmp(bdaddr, &k->bdaddr) == 0) {
11290378b597SJohan Hedberg rcu_read_unlock();
1130600a8749SAlain Michaud
1131600a8749SAlain Michaud if (hci_is_blocked_key(hdev,
1132600a8749SAlain Michaud HCI_BLOCKED_KEY_TYPE_LINKKEY,
1133600a8749SAlain Michaud k->val)) {
1134600a8749SAlain Michaud bt_dev_warn_ratelimited(hdev,
1135600a8749SAlain Michaud "Link key blocked for %pMR",
1136600a8749SAlain Michaud &k->bdaddr);
1137600a8749SAlain Michaud return NULL;
1138600a8749SAlain Michaud }
1139600a8749SAlain Michaud
114055ed8ca1SJohan Hedberg return k;
11410378b597SJohan Hedberg }
11420378b597SJohan Hedberg }
11430378b597SJohan Hedberg rcu_read_unlock();
114455ed8ca1SJohan Hedberg
114555ed8ca1SJohan Hedberg return NULL;
114655ed8ca1SJohan Hedberg }
114755ed8ca1SJohan Hedberg
hci_persistent_key(struct hci_dev * hdev,struct hci_conn * conn,u8 key_type,u8 old_key_type)1148745c0ce3SVishal Agarwal static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
1149d25e28abSJohan Hedberg u8 key_type, u8 old_key_type)
1150d25e28abSJohan Hedberg {
1151d25e28abSJohan Hedberg /* Legacy key */
1152d25e28abSJohan Hedberg if (key_type < 0x03)
1153745c0ce3SVishal Agarwal return true;
1154d25e28abSJohan Hedberg
1155d25e28abSJohan Hedberg /* Debug keys are insecure so don't store them persistently */
1156d25e28abSJohan Hedberg if (key_type == HCI_LK_DEBUG_COMBINATION)
1157745c0ce3SVishal Agarwal return false;
1158d25e28abSJohan Hedberg
1159d25e28abSJohan Hedberg /* Changed combination key and there's no previous one */
1160d25e28abSJohan Hedberg if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
1161745c0ce3SVishal Agarwal return false;
1162d25e28abSJohan Hedberg
1163d25e28abSJohan Hedberg /* Security mode 3 case */
1164d25e28abSJohan Hedberg if (!conn)
1165745c0ce3SVishal Agarwal return true;
1166d25e28abSJohan Hedberg
1167e3befab9SJohan Hedberg /* BR/EDR key derived using SC from an LE link */
1168e3befab9SJohan Hedberg if (conn->type == LE_LINK)
1169e3befab9SJohan Hedberg return true;
1170e3befab9SJohan Hedberg
1171d25e28abSJohan Hedberg /* Neither local nor remote side had no-bonding as requirement */
1172d25e28abSJohan Hedberg if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
1173745c0ce3SVishal Agarwal return true;
1174d25e28abSJohan Hedberg
1175d25e28abSJohan Hedberg /* Local side had dedicated bonding as requirement */
1176d25e28abSJohan Hedberg if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
1177745c0ce3SVishal Agarwal return true;
1178d25e28abSJohan Hedberg
1179d25e28abSJohan Hedberg /* Remote side had dedicated bonding as requirement */
1180d25e28abSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
1181745c0ce3SVishal Agarwal return true;
1182d25e28abSJohan Hedberg
1183d25e28abSJohan Hedberg /* If none of the above criteria match, then don't store the key
1184d25e28abSJohan Hedberg * persistently */
1185745c0ce3SVishal Agarwal return false;
1186d25e28abSJohan Hedberg }
1187d25e28abSJohan Hedberg
ltk_role(u8 type)1188e804d25dSJohan Hedberg static u8 ltk_role(u8 type)
118998a0b845SJohan Hedberg {
1190e804d25dSJohan Hedberg if (type == SMP_LTK)
1191e804d25dSJohan Hedberg return HCI_ROLE_MASTER;
119298a0b845SJohan Hedberg
1193e804d25dSJohan Hedberg return HCI_ROLE_SLAVE;
119498a0b845SJohan Hedberg }
119598a0b845SJohan Hedberg
hci_find_ltk(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 addr_type,u8 role)1196f3a73d97SJohan Hedberg struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
1197e804d25dSJohan Hedberg u8 addr_type, u8 role)
119875d262c2SVinicius Costa Gomes {
1199c9839a11SVinicius Costa Gomes struct smp_ltk *k;
120075d262c2SVinicius Costa Gomes
1201970d0f1bSJohan Hedberg rcu_read_lock();
1202970d0f1bSJohan Hedberg list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
12035378bc56SJohan Hedberg if (addr_type != k->bdaddr_type || bacmp(bdaddr, &k->bdaddr))
12045378bc56SJohan Hedberg continue;
12055378bc56SJohan Hedberg
1206923e2414SJohan Hedberg if (smp_ltk_is_sc(k) || ltk_role(k->type) == role) {
1207970d0f1bSJohan Hedberg rcu_read_unlock();
1208600a8749SAlain Michaud
1209600a8749SAlain Michaud if (hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_LTK,
1210600a8749SAlain Michaud k->val)) {
1211600a8749SAlain Michaud bt_dev_warn_ratelimited(hdev,
1212600a8749SAlain Michaud "LTK blocked for %pMR",
1213600a8749SAlain Michaud &k->bdaddr);
1214600a8749SAlain Michaud return NULL;
1215600a8749SAlain Michaud }
1216600a8749SAlain Michaud
121775d262c2SVinicius Costa Gomes return k;
1218970d0f1bSJohan Hedberg }
1219970d0f1bSJohan Hedberg }
1220970d0f1bSJohan Hedberg rcu_read_unlock();
122175d262c2SVinicius Costa Gomes
122275d262c2SVinicius Costa Gomes return NULL;
122375d262c2SVinicius Costa Gomes }
122475d262c2SVinicius Costa Gomes
hci_find_irk_by_rpa(struct hci_dev * hdev,bdaddr_t * rpa)1225970c4e46SJohan Hedberg struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa)
1226970c4e46SJohan Hedberg {
1227600a8749SAlain Michaud struct smp_irk *irk_to_return = NULL;
1228970c4e46SJohan Hedberg struct smp_irk *irk;
1229970c4e46SJohan Hedberg
1230adae20cbSJohan Hedberg rcu_read_lock();
1231adae20cbSJohan Hedberg list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
1232adae20cbSJohan Hedberg if (!bacmp(&irk->rpa, rpa)) {
1233600a8749SAlain Michaud irk_to_return = irk;
1234600a8749SAlain Michaud goto done;
1235970c4e46SJohan Hedberg }
1236adae20cbSJohan Hedberg }
1237970c4e46SJohan Hedberg
1238adae20cbSJohan Hedberg list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
1239defce9e8SJohan Hedberg if (smp_irk_matches(hdev, irk->val, rpa)) {
1240970c4e46SJohan Hedberg bacpy(&irk->rpa, rpa);
1241600a8749SAlain Michaud irk_to_return = irk;
1242600a8749SAlain Michaud goto done;
1243970c4e46SJohan Hedberg }
1244970c4e46SJohan Hedberg }
1245600a8749SAlain Michaud
1246600a8749SAlain Michaud done:
1247600a8749SAlain Michaud if (irk_to_return && hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK,
1248600a8749SAlain Michaud irk_to_return->val)) {
1249600a8749SAlain Michaud bt_dev_warn_ratelimited(hdev, "Identity key blocked for %pMR",
1250600a8749SAlain Michaud &irk_to_return->bdaddr);
1251600a8749SAlain Michaud irk_to_return = NULL;
1252600a8749SAlain Michaud }
1253600a8749SAlain Michaud
1254adae20cbSJohan Hedberg rcu_read_unlock();
1255970c4e46SJohan Hedberg
1256600a8749SAlain Michaud return irk_to_return;
1257970c4e46SJohan Hedberg }
1258970c4e46SJohan Hedberg
hci_find_irk_by_addr(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 addr_type)1259970c4e46SJohan Hedberg struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
1260970c4e46SJohan Hedberg u8 addr_type)
1261970c4e46SJohan Hedberg {
1262600a8749SAlain Michaud struct smp_irk *irk_to_return = NULL;
1263970c4e46SJohan Hedberg struct smp_irk *irk;
1264970c4e46SJohan Hedberg
12656cfc9988SJohan Hedberg /* Identity Address must be public or static random */
12666cfc9988SJohan Hedberg if (addr_type == ADDR_LE_DEV_RANDOM && (bdaddr->b[5] & 0xc0) != 0xc0)
12676cfc9988SJohan Hedberg return NULL;
12686cfc9988SJohan Hedberg
1269adae20cbSJohan Hedberg rcu_read_lock();
1270adae20cbSJohan Hedberg list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
1271970c4e46SJohan Hedberg if (addr_type == irk->addr_type &&
1272adae20cbSJohan Hedberg bacmp(bdaddr, &irk->bdaddr) == 0) {
1273600a8749SAlain Michaud irk_to_return = irk;
1274600a8749SAlain Michaud goto done;
1275970c4e46SJohan Hedberg }
1276adae20cbSJohan Hedberg }
1277600a8749SAlain Michaud
1278600a8749SAlain Michaud done:
1279600a8749SAlain Michaud
1280600a8749SAlain Michaud if (irk_to_return && hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK,
1281600a8749SAlain Michaud irk_to_return->val)) {
1282600a8749SAlain Michaud bt_dev_warn_ratelimited(hdev, "Identity key blocked for %pMR",
1283600a8749SAlain Michaud &irk_to_return->bdaddr);
1284600a8749SAlain Michaud irk_to_return = NULL;
1285600a8749SAlain Michaud }
1286600a8749SAlain Michaud
1287adae20cbSJohan Hedberg rcu_read_unlock();
1288970c4e46SJohan Hedberg
1289600a8749SAlain Michaud return irk_to_return;
1290970c4e46SJohan Hedberg }
1291970c4e46SJohan Hedberg
hci_add_link_key(struct hci_dev * hdev,struct hci_conn * conn,bdaddr_t * bdaddr,u8 * val,u8 type,u8 pin_len,bool * persistent)1292567fa2aaSJohan Hedberg struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
12937652ff6aSJohan Hedberg bdaddr_t *bdaddr, u8 *val, u8 type,
12947652ff6aSJohan Hedberg u8 pin_len, bool *persistent)
129555ed8ca1SJohan Hedberg {
129655ed8ca1SJohan Hedberg struct link_key *key, *old_key;
1297745c0ce3SVishal Agarwal u8 old_key_type;
129855ed8ca1SJohan Hedberg
129955ed8ca1SJohan Hedberg old_key = hci_find_link_key(hdev, bdaddr);
130055ed8ca1SJohan Hedberg if (old_key) {
130155ed8ca1SJohan Hedberg old_key_type = old_key->type;
130255ed8ca1SJohan Hedberg key = old_key;
130355ed8ca1SJohan Hedberg } else {
130412adcf3aSJohan Hedberg old_key_type = conn ? conn->key_type : 0xff;
13050a14ab41SJohan Hedberg key = kzalloc(sizeof(*key), GFP_KERNEL);
130655ed8ca1SJohan Hedberg if (!key)
1307567fa2aaSJohan Hedberg return NULL;
13080378b597SJohan Hedberg list_add_rcu(&key->list, &hdev->link_keys);
130955ed8ca1SJohan Hedberg }
131055ed8ca1SJohan Hedberg
13116ed93dc6SAndrei Emeltchenko BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
131255ed8ca1SJohan Hedberg
1313d25e28abSJohan Hedberg /* Some buggy controller combinations generate a changed
1314d25e28abSJohan Hedberg * combination key for legacy pairing even when there's no
1315d25e28abSJohan Hedberg * previous key */
1316d25e28abSJohan Hedberg if (type == HCI_LK_CHANGED_COMBINATION &&
1317a8c5fb1aSGustavo Padovan (!conn || conn->remote_auth == 0xff) && old_key_type == 0xff) {
1318d25e28abSJohan Hedberg type = HCI_LK_COMBINATION;
1319655fe6ecSJohan Hedberg if (conn)
1320655fe6ecSJohan Hedberg conn->key_type = type;
1321655fe6ecSJohan Hedberg }
1322d25e28abSJohan Hedberg
132355ed8ca1SJohan Hedberg bacpy(&key->bdaddr, bdaddr);
13249b3b4460SAndrei Emeltchenko memcpy(key->val, val, HCI_LINK_KEY_SIZE);
132555ed8ca1SJohan Hedberg key->pin_len = pin_len;
132655ed8ca1SJohan Hedberg
1327b6020ba0SWaldemar Rymarkiewicz if (type == HCI_LK_CHANGED_COMBINATION)
132855ed8ca1SJohan Hedberg key->type = old_key_type;
13294748fed2SJohan Hedberg else
13304748fed2SJohan Hedberg key->type = type;
13314748fed2SJohan Hedberg
13327652ff6aSJohan Hedberg if (persistent)
13337652ff6aSJohan Hedberg *persistent = hci_persistent_key(hdev, conn, type,
13347652ff6aSJohan Hedberg old_key_type);
13354df378a1SJohan Hedberg
1336567fa2aaSJohan Hedberg return key;
133755ed8ca1SJohan Hedberg }
133855ed8ca1SJohan Hedberg
hci_add_ltk(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 addr_type,u8 type,u8 authenticated,u8 tk[16],u8 enc_size,__le16 ediv,__le64 rand)1339ca9142b8SJohan Hedberg struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
134035d70271SJohan Hedberg u8 addr_type, u8 type, u8 authenticated,
1341fe39c7b2SMarcel Holtmann u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand)
134275d262c2SVinicius Costa Gomes {
1343c9839a11SVinicius Costa Gomes struct smp_ltk *key, *old_key;
1344e804d25dSJohan Hedberg u8 role = ltk_role(type);
134575d262c2SVinicius Costa Gomes
1346f3a73d97SJohan Hedberg old_key = hci_find_ltk(hdev, bdaddr, addr_type, role);
1347c9839a11SVinicius Costa Gomes if (old_key)
134875d262c2SVinicius Costa Gomes key = old_key;
1349c9839a11SVinicius Costa Gomes else {
13500a14ab41SJohan Hedberg key = kzalloc(sizeof(*key), GFP_KERNEL);
135175d262c2SVinicius Costa Gomes if (!key)
1352ca9142b8SJohan Hedberg return NULL;
1353970d0f1bSJohan Hedberg list_add_rcu(&key->list, &hdev->long_term_keys);
135475d262c2SVinicius Costa Gomes }
135575d262c2SVinicius Costa Gomes
135675d262c2SVinicius Costa Gomes bacpy(&key->bdaddr, bdaddr);
1357c9839a11SVinicius Costa Gomes key->bdaddr_type = addr_type;
1358c9839a11SVinicius Costa Gomes memcpy(key->val, tk, sizeof(key->val));
1359c9839a11SVinicius Costa Gomes key->authenticated = authenticated;
1360c9839a11SVinicius Costa Gomes key->ediv = ediv;
1361fe39c7b2SMarcel Holtmann key->rand = rand;
1362c9839a11SVinicius Costa Gomes key->enc_size = enc_size;
1363c9839a11SVinicius Costa Gomes key->type = type;
136475d262c2SVinicius Costa Gomes
1365ca9142b8SJohan Hedberg return key;
136675d262c2SVinicius Costa Gomes }
136775d262c2SVinicius Costa Gomes
hci_add_irk(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 addr_type,u8 val[16],bdaddr_t * rpa)1368ca9142b8SJohan Hedberg struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
1369ca9142b8SJohan Hedberg u8 addr_type, u8 val[16], bdaddr_t *rpa)
1370970c4e46SJohan Hedberg {
1371970c4e46SJohan Hedberg struct smp_irk *irk;
1372970c4e46SJohan Hedberg
1373970c4e46SJohan Hedberg irk = hci_find_irk_by_addr(hdev, bdaddr, addr_type);
1374970c4e46SJohan Hedberg if (!irk) {
1375970c4e46SJohan Hedberg irk = kzalloc(sizeof(*irk), GFP_KERNEL);
1376970c4e46SJohan Hedberg if (!irk)
1377ca9142b8SJohan Hedberg return NULL;
1378970c4e46SJohan Hedberg
1379970c4e46SJohan Hedberg bacpy(&irk->bdaddr, bdaddr);
1380970c4e46SJohan Hedberg irk->addr_type = addr_type;
1381970c4e46SJohan Hedberg
1382adae20cbSJohan Hedberg list_add_rcu(&irk->list, &hdev->identity_resolving_keys);
1383970c4e46SJohan Hedberg }
1384970c4e46SJohan Hedberg
1385970c4e46SJohan Hedberg memcpy(irk->val, val, 16);
1386970c4e46SJohan Hedberg bacpy(&irk->rpa, rpa);
1387970c4e46SJohan Hedberg
1388ca9142b8SJohan Hedberg return irk;
1389970c4e46SJohan Hedberg }
1390970c4e46SJohan Hedberg
hci_remove_link_key(struct hci_dev * hdev,bdaddr_t * bdaddr)139155ed8ca1SJohan Hedberg int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
139255ed8ca1SJohan Hedberg {
139355ed8ca1SJohan Hedberg struct link_key *key;
139455ed8ca1SJohan Hedberg
139555ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, bdaddr);
139655ed8ca1SJohan Hedberg if (!key)
139755ed8ca1SJohan Hedberg return -ENOENT;
139855ed8ca1SJohan Hedberg
13996ed93dc6SAndrei Emeltchenko BT_DBG("%s removing %pMR", hdev->name, bdaddr);
140055ed8ca1SJohan Hedberg
14010378b597SJohan Hedberg list_del_rcu(&key->list);
14020378b597SJohan Hedberg kfree_rcu(key, rcu);
140355ed8ca1SJohan Hedberg
140455ed8ca1SJohan Hedberg return 0;
140555ed8ca1SJohan Hedberg }
140655ed8ca1SJohan Hedberg
hci_remove_ltk(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 bdaddr_type)1407e0b2b27eSJohan Hedberg int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
1408b899efafSVinicius Costa Gomes {
1409c5d2b6faSLuiz Augusto von Dentz struct smp_ltk *k, *tmp;
1410c51ffa0bSJohan Hedberg int removed = 0;
1411b899efafSVinicius Costa Gomes
1412c5d2b6faSLuiz Augusto von Dentz list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
1413e0b2b27eSJohan Hedberg if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type)
1414b899efafSVinicius Costa Gomes continue;
1415b899efafSVinicius Costa Gomes
14166ed93dc6SAndrei Emeltchenko BT_DBG("%s removing %pMR", hdev->name, bdaddr);
1417b899efafSVinicius Costa Gomes
1418970d0f1bSJohan Hedberg list_del_rcu(&k->list);
1419970d0f1bSJohan Hedberg kfree_rcu(k, rcu);
1420c51ffa0bSJohan Hedberg removed++;
1421b899efafSVinicius Costa Gomes }
1422b899efafSVinicius Costa Gomes
1423c51ffa0bSJohan Hedberg return removed ? 0 : -ENOENT;
1424b899efafSVinicius Costa Gomes }
1425b899efafSVinicius Costa Gomes
hci_remove_irk(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 addr_type)1426a7ec7338SJohan Hedberg void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type)
1427a7ec7338SJohan Hedberg {
1428c5d2b6faSLuiz Augusto von Dentz struct smp_irk *k, *tmp;
1429a7ec7338SJohan Hedberg
1430c5d2b6faSLuiz Augusto von Dentz list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
1431a7ec7338SJohan Hedberg if (bacmp(bdaddr, &k->bdaddr) || k->addr_type != addr_type)
1432a7ec7338SJohan Hedberg continue;
1433a7ec7338SJohan Hedberg
1434a7ec7338SJohan Hedberg BT_DBG("%s removing %pMR", hdev->name, bdaddr);
1435a7ec7338SJohan Hedberg
1436adae20cbSJohan Hedberg list_del_rcu(&k->list);
1437adae20cbSJohan Hedberg kfree_rcu(k, rcu);
1438a7ec7338SJohan Hedberg }
1439a7ec7338SJohan Hedberg }
1440a7ec7338SJohan Hedberg
hci_bdaddr_is_paired(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 type)144155e76b38SJohan Hedberg bool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
144255e76b38SJohan Hedberg {
144355e76b38SJohan Hedberg struct smp_ltk *k;
14444ba9faf3SJohan Hedberg struct smp_irk *irk;
144555e76b38SJohan Hedberg u8 addr_type;
144655e76b38SJohan Hedberg
144755e76b38SJohan Hedberg if (type == BDADDR_BREDR) {
144855e76b38SJohan Hedberg if (hci_find_link_key(hdev, bdaddr))
144955e76b38SJohan Hedberg return true;
145055e76b38SJohan Hedberg return false;
145155e76b38SJohan Hedberg }
145255e76b38SJohan Hedberg
145355e76b38SJohan Hedberg /* Convert to HCI addr type which struct smp_ltk uses */
145455e76b38SJohan Hedberg if (type == BDADDR_LE_PUBLIC)
145555e76b38SJohan Hedberg addr_type = ADDR_LE_DEV_PUBLIC;
145655e76b38SJohan Hedberg else
145755e76b38SJohan Hedberg addr_type = ADDR_LE_DEV_RANDOM;
145855e76b38SJohan Hedberg
14594ba9faf3SJohan Hedberg irk = hci_get_irk(hdev, bdaddr, addr_type);
14604ba9faf3SJohan Hedberg if (irk) {
14614ba9faf3SJohan Hedberg bdaddr = &irk->bdaddr;
14624ba9faf3SJohan Hedberg addr_type = irk->addr_type;
14634ba9faf3SJohan Hedberg }
14644ba9faf3SJohan Hedberg
146555e76b38SJohan Hedberg rcu_read_lock();
146655e76b38SJohan Hedberg list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
146787c8b28dSJohan Hedberg if (k->bdaddr_type == addr_type && !bacmp(bdaddr, &k->bdaddr)) {
146887c8b28dSJohan Hedberg rcu_read_unlock();
146955e76b38SJohan Hedberg return true;
147055e76b38SJohan Hedberg }
147187c8b28dSJohan Hedberg }
147255e76b38SJohan Hedberg rcu_read_unlock();
147355e76b38SJohan Hedberg
147455e76b38SJohan Hedberg return false;
147555e76b38SJohan Hedberg }
147655e76b38SJohan Hedberg
14776bd32326SVille Tervo /* HCI command timer function */
hci_cmd_timeout(struct work_struct * work)147865cc2b49SMarcel Holtmann static void hci_cmd_timeout(struct work_struct *work)
14796bd32326SVille Tervo {
148065cc2b49SMarcel Holtmann struct hci_dev *hdev = container_of(work, struct hci_dev,
148165cc2b49SMarcel Holtmann cmd_timer.work);
14826bd32326SVille Tervo
14832af7aa66SLuiz Augusto von Dentz if (hdev->req_skb) {
14842af7aa66SLuiz Augusto von Dentz u16 opcode = hci_skb_opcode(hdev->req_skb);
1485bda4f23aSAndrei Emeltchenko
14862064ee33SMarcel Holtmann bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode);
14870ce1229cSLuiz Augusto von Dentz
14880ce1229cSLuiz Augusto von Dentz hci_cmd_sync_cancel_sync(hdev, ETIMEDOUT);
1489bda4f23aSAndrei Emeltchenko } else {
14902064ee33SMarcel Holtmann bt_dev_err(hdev, "command tx timeout");
1491bda4f23aSAndrei Emeltchenko }
1492bda4f23aSAndrei Emeltchenko
1493e2bef384SRajat Jain if (hdev->cmd_timeout)
1494e2bef384SRajat Jain hdev->cmd_timeout(hdev);
1495e2bef384SRajat Jain
14966bd32326SVille Tervo atomic_set(&hdev->cmd_cnt, 1);
1497c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work);
14986bd32326SVille Tervo }
14996bd32326SVille Tervo
1500de75cd0dSManish Mandlik /* HCI ncmd timer function */
hci_ncmd_timeout(struct work_struct * work)1501de75cd0dSManish Mandlik static void hci_ncmd_timeout(struct work_struct *work)
1502de75cd0dSManish Mandlik {
1503de75cd0dSManish Mandlik struct hci_dev *hdev = container_of(work, struct hci_dev,
1504de75cd0dSManish Mandlik ncmd_timer.work);
1505de75cd0dSManish Mandlik
1506de75cd0dSManish Mandlik bt_dev_err(hdev, "Controller not accepting commands anymore: ncmd = 0");
1507de75cd0dSManish Mandlik
1508de75cd0dSManish Mandlik /* During HCI_INIT phase no events can be injected if the ncmd timer
1509de75cd0dSManish Mandlik * triggers since the procedure has its own timeout handling.
1510de75cd0dSManish Mandlik */
1511de75cd0dSManish Mandlik if (test_bit(HCI_INIT, &hdev->flags))
1512de75cd0dSManish Mandlik return;
1513de75cd0dSManish Mandlik
1514de75cd0dSManish Mandlik /* This is an irrecoverable state, inject hardware error event */
1515de75cd0dSManish Mandlik hci_reset_dev(hdev);
1516de75cd0dSManish Mandlik }
1517de75cd0dSManish Mandlik
hci_find_remote_oob_data(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 bdaddr_type)15182763eda6SSzymon Janc struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
15196928a924SJohan Hedberg bdaddr_t *bdaddr, u8 bdaddr_type)
15202763eda6SSzymon Janc {
15212763eda6SSzymon Janc struct oob_data *data;
15222763eda6SSzymon Janc
15236928a924SJohan Hedberg list_for_each_entry(data, &hdev->remote_oob_data, list) {
15246928a924SJohan Hedberg if (bacmp(bdaddr, &data->bdaddr) != 0)
15256928a924SJohan Hedberg continue;
15266928a924SJohan Hedberg if (data->bdaddr_type != bdaddr_type)
15276928a924SJohan Hedberg continue;
15282763eda6SSzymon Janc return data;
15296928a924SJohan Hedberg }
15302763eda6SSzymon Janc
15312763eda6SSzymon Janc return NULL;
15322763eda6SSzymon Janc }
15332763eda6SSzymon Janc
hci_remove_remote_oob_data(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 bdaddr_type)15346928a924SJohan Hedberg int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
15356928a924SJohan Hedberg u8 bdaddr_type)
15362763eda6SSzymon Janc {
15372763eda6SSzymon Janc struct oob_data *data;
15382763eda6SSzymon Janc
15396928a924SJohan Hedberg data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
15402763eda6SSzymon Janc if (!data)
15412763eda6SSzymon Janc return -ENOENT;
15422763eda6SSzymon Janc
15436928a924SJohan Hedberg BT_DBG("%s removing %pMR (%u)", hdev->name, bdaddr, bdaddr_type);
15442763eda6SSzymon Janc
15452763eda6SSzymon Janc list_del(&data->list);
15462763eda6SSzymon Janc kfree(data);
15472763eda6SSzymon Janc
15482763eda6SSzymon Janc return 0;
15492763eda6SSzymon Janc }
15502763eda6SSzymon Janc
hci_remote_oob_data_clear(struct hci_dev * hdev)155135f7498aSJohan Hedberg void hci_remote_oob_data_clear(struct hci_dev *hdev)
15522763eda6SSzymon Janc {
15532763eda6SSzymon Janc struct oob_data *data, *n;
15542763eda6SSzymon Janc
15552763eda6SSzymon Janc list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) {
15562763eda6SSzymon Janc list_del(&data->list);
15572763eda6SSzymon Janc kfree(data);
15582763eda6SSzymon Janc }
15592763eda6SSzymon Janc }
15602763eda6SSzymon Janc
hci_add_remote_oob_data(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 bdaddr_type,u8 * hash192,u8 * rand192,u8 * hash256,u8 * rand256)15610798872eSMarcel Holtmann int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
15626928a924SJohan Hedberg u8 bdaddr_type, u8 *hash192, u8 *rand192,
156338da1703SJohan Hedberg u8 *hash256, u8 *rand256)
15640798872eSMarcel Holtmann {
15650798872eSMarcel Holtmann struct oob_data *data;
15660798872eSMarcel Holtmann
15676928a924SJohan Hedberg data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
15680798872eSMarcel Holtmann if (!data) {
15690a14ab41SJohan Hedberg data = kmalloc(sizeof(*data), GFP_KERNEL);
15700798872eSMarcel Holtmann if (!data)
15710798872eSMarcel Holtmann return -ENOMEM;
15720798872eSMarcel Holtmann
15730798872eSMarcel Holtmann bacpy(&data->bdaddr, bdaddr);
15746928a924SJohan Hedberg data->bdaddr_type = bdaddr_type;
15750798872eSMarcel Holtmann list_add(&data->list, &hdev->remote_oob_data);
15760798872eSMarcel Holtmann }
15770798872eSMarcel Holtmann
157881328d5cSJohan Hedberg if (hash192 && rand192) {
15790798872eSMarcel Holtmann memcpy(data->hash192, hash192, sizeof(data->hash192));
158038da1703SJohan Hedberg memcpy(data->rand192, rand192, sizeof(data->rand192));
1581f7697b16SMarcel Holtmann if (hash256 && rand256)
1582f7697b16SMarcel Holtmann data->present = 0x03;
158381328d5cSJohan Hedberg } else {
158481328d5cSJohan Hedberg memset(data->hash192, 0, sizeof(data->hash192));
158581328d5cSJohan Hedberg memset(data->rand192, 0, sizeof(data->rand192));
1586f7697b16SMarcel Holtmann if (hash256 && rand256)
1587f7697b16SMarcel Holtmann data->present = 0x02;
1588f7697b16SMarcel Holtmann else
1589f7697b16SMarcel Holtmann data->present = 0x00;
159081328d5cSJohan Hedberg }
15910798872eSMarcel Holtmann
159281328d5cSJohan Hedberg if (hash256 && rand256) {
15930798872eSMarcel Holtmann memcpy(data->hash256, hash256, sizeof(data->hash256));
159438da1703SJohan Hedberg memcpy(data->rand256, rand256, sizeof(data->rand256));
159581328d5cSJohan Hedberg } else {
159681328d5cSJohan Hedberg memset(data->hash256, 0, sizeof(data->hash256));
159781328d5cSJohan Hedberg memset(data->rand256, 0, sizeof(data->rand256));
1598f7697b16SMarcel Holtmann if (hash192 && rand192)
1599f7697b16SMarcel Holtmann data->present = 0x01;
160081328d5cSJohan Hedberg }
16010798872eSMarcel Holtmann
16026ed93dc6SAndrei Emeltchenko BT_DBG("%s for %pMR", hdev->name, bdaddr);
16032763eda6SSzymon Janc
16042763eda6SSzymon Janc return 0;
16052763eda6SSzymon Janc }
16062763eda6SSzymon Janc
1607d2609b34SFlorian Grandel /* This function requires the caller holds hdev->lock */
hci_find_adv_instance(struct hci_dev * hdev,u8 instance)1608d2609b34SFlorian Grandel struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance)
1609d2609b34SFlorian Grandel {
1610d2609b34SFlorian Grandel struct adv_info *adv_instance;
1611d2609b34SFlorian Grandel
1612d2609b34SFlorian Grandel list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
1613d2609b34SFlorian Grandel if (adv_instance->instance == instance)
1614d2609b34SFlorian Grandel return adv_instance;
1615d2609b34SFlorian Grandel }
1616d2609b34SFlorian Grandel
1617d2609b34SFlorian Grandel return NULL;
1618d2609b34SFlorian Grandel }
1619d2609b34SFlorian Grandel
1620d2609b34SFlorian Grandel /* This function requires the caller holds hdev->lock */
hci_get_next_instance(struct hci_dev * hdev,u8 instance)162174b93e9fSPrasanna Karthik struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance)
162274b93e9fSPrasanna Karthik {
1623d2609b34SFlorian Grandel struct adv_info *cur_instance;
1624d2609b34SFlorian Grandel
1625d2609b34SFlorian Grandel cur_instance = hci_find_adv_instance(hdev, instance);
1626d2609b34SFlorian Grandel if (!cur_instance)
1627d2609b34SFlorian Grandel return NULL;
1628d2609b34SFlorian Grandel
1629d2609b34SFlorian Grandel if (cur_instance == list_last_entry(&hdev->adv_instances,
1630d2609b34SFlorian Grandel struct adv_info, list))
1631d2609b34SFlorian Grandel return list_first_entry(&hdev->adv_instances,
1632d2609b34SFlorian Grandel struct adv_info, list);
1633d2609b34SFlorian Grandel else
1634d2609b34SFlorian Grandel return list_next_entry(cur_instance, list);
1635d2609b34SFlorian Grandel }
1636d2609b34SFlorian Grandel
1637d2609b34SFlorian Grandel /* This function requires the caller holds hdev->lock */
hci_remove_adv_instance(struct hci_dev * hdev,u8 instance)1638d2609b34SFlorian Grandel int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance)
1639d2609b34SFlorian Grandel {
1640d2609b34SFlorian Grandel struct adv_info *adv_instance;
1641d2609b34SFlorian Grandel
1642d2609b34SFlorian Grandel adv_instance = hci_find_adv_instance(hdev, instance);
1643d2609b34SFlorian Grandel if (!adv_instance)
1644d2609b34SFlorian Grandel return -ENOENT;
1645d2609b34SFlorian Grandel
1646d2609b34SFlorian Grandel BT_DBG("%s removing %dMR", hdev->name, instance);
1647d2609b34SFlorian Grandel
1648cab054abSJohan Hedberg if (hdev->cur_adv_instance == instance) {
1649cab054abSJohan Hedberg if (hdev->adv_instance_timeout) {
16505d900e46SFlorian Grandel cancel_delayed_work(&hdev->adv_instance_expire);
16515d900e46SFlorian Grandel hdev->adv_instance_timeout = 0;
16525d900e46SFlorian Grandel }
1653cab054abSJohan Hedberg hdev->cur_adv_instance = 0x00;
1654cab054abSJohan Hedberg }
16555d900e46SFlorian Grandel
1656a73c046aSJaganath Kanakkassery cancel_delayed_work_sync(&adv_instance->rpa_expired_cb);
1657a73c046aSJaganath Kanakkassery
1658d2609b34SFlorian Grandel list_del(&adv_instance->list);
1659d2609b34SFlorian Grandel kfree(adv_instance);
1660d2609b34SFlorian Grandel
1661d2609b34SFlorian Grandel hdev->adv_instance_cnt--;
1662d2609b34SFlorian Grandel
1663d2609b34SFlorian Grandel return 0;
1664d2609b34SFlorian Grandel }
1665d2609b34SFlorian Grandel
hci_adv_instances_set_rpa_expired(struct hci_dev * hdev,bool rpa_expired)1666a73c046aSJaganath Kanakkassery void hci_adv_instances_set_rpa_expired(struct hci_dev *hdev, bool rpa_expired)
1667a73c046aSJaganath Kanakkassery {
1668a73c046aSJaganath Kanakkassery struct adv_info *adv_instance, *n;
1669a73c046aSJaganath Kanakkassery
1670a73c046aSJaganath Kanakkassery list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list)
1671a73c046aSJaganath Kanakkassery adv_instance->rpa_expired = rpa_expired;
1672a73c046aSJaganath Kanakkassery }
1673a73c046aSJaganath Kanakkassery
1674d2609b34SFlorian Grandel /* This function requires the caller holds hdev->lock */
hci_adv_instances_clear(struct hci_dev * hdev)1675d2609b34SFlorian Grandel void hci_adv_instances_clear(struct hci_dev *hdev)
1676d2609b34SFlorian Grandel {
1677d2609b34SFlorian Grandel struct adv_info *adv_instance, *n;
1678d2609b34SFlorian Grandel
16795d900e46SFlorian Grandel if (hdev->adv_instance_timeout) {
16805d900e46SFlorian Grandel cancel_delayed_work(&hdev->adv_instance_expire);
16815d900e46SFlorian Grandel hdev->adv_instance_timeout = 0;
16825d900e46SFlorian Grandel }
16835d900e46SFlorian Grandel
1684d2609b34SFlorian Grandel list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) {
1685a73c046aSJaganath Kanakkassery cancel_delayed_work_sync(&adv_instance->rpa_expired_cb);
1686d2609b34SFlorian Grandel list_del(&adv_instance->list);
1687d2609b34SFlorian Grandel kfree(adv_instance);
1688d2609b34SFlorian Grandel }
1689d2609b34SFlorian Grandel
1690d2609b34SFlorian Grandel hdev->adv_instance_cnt = 0;
1691cab054abSJohan Hedberg hdev->cur_adv_instance = 0x00;
1692d2609b34SFlorian Grandel }
1693d2609b34SFlorian Grandel
adv_instance_rpa_expired(struct work_struct * work)1694a73c046aSJaganath Kanakkassery static void adv_instance_rpa_expired(struct work_struct *work)
1695a73c046aSJaganath Kanakkassery {
1696a73c046aSJaganath Kanakkassery struct adv_info *adv_instance = container_of(work, struct adv_info,
1697a73c046aSJaganath Kanakkassery rpa_expired_cb.work);
1698a73c046aSJaganath Kanakkassery
1699a73c046aSJaganath Kanakkassery BT_DBG("");
1700a73c046aSJaganath Kanakkassery
1701a73c046aSJaganath Kanakkassery adv_instance->rpa_expired = true;
1702a73c046aSJaganath Kanakkassery }
1703a73c046aSJaganath Kanakkassery
1704d2609b34SFlorian Grandel /* This function requires the caller holds hdev->lock */
hci_add_adv_instance(struct hci_dev * hdev,u8 instance,u32 flags,u16 adv_data_len,u8 * adv_data,u16 scan_rsp_len,u8 * scan_rsp_data,u16 timeout,u16 duration,s8 tx_power,u32 min_interval,u32 max_interval,u8 mesh_handle)1705eca0ae4aSLuiz Augusto von Dentz struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
1706eca0ae4aSLuiz Augusto von Dentz u32 flags, u16 adv_data_len, u8 *adv_data,
1707d2609b34SFlorian Grandel u16 scan_rsp_len, u8 *scan_rsp_data,
17089bf9f4b6SDaniel Winkler u16 timeout, u16 duration, s8 tx_power,
1709b338d917SBrian Gix u32 min_interval, u32 max_interval,
1710b338d917SBrian Gix u8 mesh_handle)
1711d2609b34SFlorian Grandel {
1712eca0ae4aSLuiz Augusto von Dentz struct adv_info *adv;
1713d2609b34SFlorian Grandel
1714eca0ae4aSLuiz Augusto von Dentz adv = hci_find_adv_instance(hdev, instance);
1715eca0ae4aSLuiz Augusto von Dentz if (adv) {
1716eca0ae4aSLuiz Augusto von Dentz memset(adv->adv_data, 0, sizeof(adv->adv_data));
1717eca0ae4aSLuiz Augusto von Dentz memset(adv->scan_rsp_data, 0, sizeof(adv->scan_rsp_data));
1718eca0ae4aSLuiz Augusto von Dentz memset(adv->per_adv_data, 0, sizeof(adv->per_adv_data));
1719d2609b34SFlorian Grandel } else {
17201d0fac2cSLuiz Augusto von Dentz if (hdev->adv_instance_cnt >= hdev->le_num_of_adv_sets ||
1721b338d917SBrian Gix instance < 1 || instance > hdev->le_num_of_adv_sets + 1)
1722eca0ae4aSLuiz Augusto von Dentz return ERR_PTR(-EOVERFLOW);
1723d2609b34SFlorian Grandel
1724eca0ae4aSLuiz Augusto von Dentz adv = kzalloc(sizeof(*adv), GFP_KERNEL);
1725eca0ae4aSLuiz Augusto von Dentz if (!adv)
1726eca0ae4aSLuiz Augusto von Dentz return ERR_PTR(-ENOMEM);
1727d2609b34SFlorian Grandel
1728eca0ae4aSLuiz Augusto von Dentz adv->pending = true;
1729eca0ae4aSLuiz Augusto von Dentz adv->instance = instance;
1730eca0ae4aSLuiz Augusto von Dentz list_add(&adv->list, &hdev->adv_instances);
1731d2609b34SFlorian Grandel hdev->adv_instance_cnt++;
1732d2609b34SFlorian Grandel }
1733d2609b34SFlorian Grandel
1734eca0ae4aSLuiz Augusto von Dentz adv->flags = flags;
1735eca0ae4aSLuiz Augusto von Dentz adv->min_interval = min_interval;
1736eca0ae4aSLuiz Augusto von Dentz adv->max_interval = max_interval;
1737eca0ae4aSLuiz Augusto von Dentz adv->tx_power = tx_power;
1738b338d917SBrian Gix /* Defining a mesh_handle changes the timing units to ms,
1739b338d917SBrian Gix * rather than seconds, and ties the instance to the requested
1740b338d917SBrian Gix * mesh_tx queue.
1741b338d917SBrian Gix */
1742b338d917SBrian Gix adv->mesh = mesh_handle;
1743d2609b34SFlorian Grandel
174434a718bcSLuiz Augusto von Dentz hci_set_adv_instance_data(hdev, instance, adv_data_len, adv_data,
174534a718bcSLuiz Augusto von Dentz scan_rsp_len, scan_rsp_data);
1746d2609b34SFlorian Grandel
1747eca0ae4aSLuiz Augusto von Dentz adv->timeout = timeout;
1748eca0ae4aSLuiz Augusto von Dentz adv->remaining_time = timeout;
1749d2609b34SFlorian Grandel
1750d2609b34SFlorian Grandel if (duration == 0)
1751eca0ae4aSLuiz Augusto von Dentz adv->duration = hdev->def_multi_adv_rotation_duration;
1752d2609b34SFlorian Grandel else
1753eca0ae4aSLuiz Augusto von Dentz adv->duration = duration;
1754d2609b34SFlorian Grandel
1755eca0ae4aSLuiz Augusto von Dentz INIT_DELAYED_WORK(&adv->rpa_expired_cb, adv_instance_rpa_expired);
1756a73c046aSJaganath Kanakkassery
1757d2609b34SFlorian Grandel BT_DBG("%s for %dMR", hdev->name, instance);
1758d2609b34SFlorian Grandel
1759eca0ae4aSLuiz Augusto von Dentz return adv;
1760eca0ae4aSLuiz Augusto von Dentz }
1761eca0ae4aSLuiz Augusto von Dentz
1762eca0ae4aSLuiz Augusto von Dentz /* This function requires the caller holds hdev->lock */
hci_add_per_instance(struct hci_dev * hdev,u8 instance,u32 flags,u8 data_len,u8 * data,u32 min_interval,u32 max_interval)1763eca0ae4aSLuiz Augusto von Dentz struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
1764eca0ae4aSLuiz Augusto von Dentz u32 flags, u8 data_len, u8 *data,
1765eca0ae4aSLuiz Augusto von Dentz u32 min_interval, u32 max_interval)
1766eca0ae4aSLuiz Augusto von Dentz {
1767eca0ae4aSLuiz Augusto von Dentz struct adv_info *adv;
1768eca0ae4aSLuiz Augusto von Dentz
1769eca0ae4aSLuiz Augusto von Dentz adv = hci_add_adv_instance(hdev, instance, flags, 0, NULL, 0, NULL,
1770eca0ae4aSLuiz Augusto von Dentz 0, 0, HCI_ADV_TX_POWER_NO_PREFERENCE,
1771b338d917SBrian Gix min_interval, max_interval, 0);
1772eca0ae4aSLuiz Augusto von Dentz if (IS_ERR(adv))
1773eca0ae4aSLuiz Augusto von Dentz return adv;
1774eca0ae4aSLuiz Augusto von Dentz
1775eca0ae4aSLuiz Augusto von Dentz adv->periodic = true;
1776eca0ae4aSLuiz Augusto von Dentz adv->per_adv_data_len = data_len;
1777eca0ae4aSLuiz Augusto von Dentz
1778eca0ae4aSLuiz Augusto von Dentz if (data)
1779eca0ae4aSLuiz Augusto von Dentz memcpy(adv->per_adv_data, data, data_len);
1780eca0ae4aSLuiz Augusto von Dentz
1781eca0ae4aSLuiz Augusto von Dentz return adv;
1782d2609b34SFlorian Grandel }
1783d2609b34SFlorian Grandel
1784e5e1e7fdSMiao-chen Chou /* This function requires the caller holds hdev->lock */
hci_set_adv_instance_data(struct hci_dev * hdev,u8 instance,u16 adv_data_len,u8 * adv_data,u16 scan_rsp_len,u8 * scan_rsp_data)178531aab5c2SDaniel Winkler int hci_set_adv_instance_data(struct hci_dev *hdev, u8 instance,
178631aab5c2SDaniel Winkler u16 adv_data_len, u8 *adv_data,
178731aab5c2SDaniel Winkler u16 scan_rsp_len, u8 *scan_rsp_data)
178831aab5c2SDaniel Winkler {
178934a718bcSLuiz Augusto von Dentz struct adv_info *adv;
179031aab5c2SDaniel Winkler
179134a718bcSLuiz Augusto von Dentz adv = hci_find_adv_instance(hdev, instance);
179231aab5c2SDaniel Winkler
179331aab5c2SDaniel Winkler /* If advertisement doesn't exist, we can't modify its data */
179434a718bcSLuiz Augusto von Dentz if (!adv)
179531aab5c2SDaniel Winkler return -ENOENT;
179631aab5c2SDaniel Winkler
179734a718bcSLuiz Augusto von Dentz if (adv_data_len && ADV_DATA_CMP(adv, adv_data, adv_data_len)) {
179834a718bcSLuiz Augusto von Dentz memset(adv->adv_data, 0, sizeof(adv->adv_data));
179934a718bcSLuiz Augusto von Dentz memcpy(adv->adv_data, adv_data, adv_data_len);
180034a718bcSLuiz Augusto von Dentz adv->adv_data_len = adv_data_len;
180134a718bcSLuiz Augusto von Dentz adv->adv_data_changed = true;
180231aab5c2SDaniel Winkler }
180331aab5c2SDaniel Winkler
180434a718bcSLuiz Augusto von Dentz if (scan_rsp_len && SCAN_RSP_CMP(adv, scan_rsp_data, scan_rsp_len)) {
180534a718bcSLuiz Augusto von Dentz memset(adv->scan_rsp_data, 0, sizeof(adv->scan_rsp_data));
180634a718bcSLuiz Augusto von Dentz memcpy(adv->scan_rsp_data, scan_rsp_data, scan_rsp_len);
180734a718bcSLuiz Augusto von Dentz adv->scan_rsp_len = scan_rsp_len;
180834a718bcSLuiz Augusto von Dentz adv->scan_rsp_changed = true;
180931aab5c2SDaniel Winkler }
181031aab5c2SDaniel Winkler
181134a718bcSLuiz Augusto von Dentz /* Mark as changed if there are flags which would affect it */
181234a718bcSLuiz Augusto von Dentz if (((adv->flags & MGMT_ADV_FLAG_APPEARANCE) && hdev->appearance) ||
181334a718bcSLuiz Augusto von Dentz adv->flags & MGMT_ADV_FLAG_LOCAL_NAME)
181434a718bcSLuiz Augusto von Dentz adv->scan_rsp_changed = true;
181534a718bcSLuiz Augusto von Dentz
181631aab5c2SDaniel Winkler return 0;
181731aab5c2SDaniel Winkler }
181831aab5c2SDaniel Winkler
181931aab5c2SDaniel Winkler /* This function requires the caller holds hdev->lock */
hci_adv_instance_flags(struct hci_dev * hdev,u8 instance)182001ce70b0SLuiz Augusto von Dentz u32 hci_adv_instance_flags(struct hci_dev *hdev, u8 instance)
182101ce70b0SLuiz Augusto von Dentz {
182201ce70b0SLuiz Augusto von Dentz u32 flags;
182301ce70b0SLuiz Augusto von Dentz struct adv_info *adv;
182401ce70b0SLuiz Augusto von Dentz
182501ce70b0SLuiz Augusto von Dentz if (instance == 0x00) {
182601ce70b0SLuiz Augusto von Dentz /* Instance 0 always manages the "Tx Power" and "Flags"
182701ce70b0SLuiz Augusto von Dentz * fields
182801ce70b0SLuiz Augusto von Dentz */
182901ce70b0SLuiz Augusto von Dentz flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
183001ce70b0SLuiz Augusto von Dentz
183101ce70b0SLuiz Augusto von Dentz /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting
183201ce70b0SLuiz Augusto von Dentz * corresponds to the "connectable" instance flag.
183301ce70b0SLuiz Augusto von Dentz */
183401ce70b0SLuiz Augusto von Dentz if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
183501ce70b0SLuiz Augusto von Dentz flags |= MGMT_ADV_FLAG_CONNECTABLE;
183601ce70b0SLuiz Augusto von Dentz
183701ce70b0SLuiz Augusto von Dentz if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
183801ce70b0SLuiz Augusto von Dentz flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
183901ce70b0SLuiz Augusto von Dentz else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
184001ce70b0SLuiz Augusto von Dentz flags |= MGMT_ADV_FLAG_DISCOV;
184101ce70b0SLuiz Augusto von Dentz
184201ce70b0SLuiz Augusto von Dentz return flags;
184301ce70b0SLuiz Augusto von Dentz }
184401ce70b0SLuiz Augusto von Dentz
184501ce70b0SLuiz Augusto von Dentz adv = hci_find_adv_instance(hdev, instance);
184601ce70b0SLuiz Augusto von Dentz
184701ce70b0SLuiz Augusto von Dentz /* Return 0 when we got an invalid instance identifier. */
184801ce70b0SLuiz Augusto von Dentz if (!adv)
184901ce70b0SLuiz Augusto von Dentz return 0;
185001ce70b0SLuiz Augusto von Dentz
185101ce70b0SLuiz Augusto von Dentz return adv->flags;
185201ce70b0SLuiz Augusto von Dentz }
185301ce70b0SLuiz Augusto von Dentz
hci_adv_instance_is_scannable(struct hci_dev * hdev,u8 instance)185401ce70b0SLuiz Augusto von Dentz bool hci_adv_instance_is_scannable(struct hci_dev *hdev, u8 instance)
185501ce70b0SLuiz Augusto von Dentz {
185601ce70b0SLuiz Augusto von Dentz struct adv_info *adv;
185701ce70b0SLuiz Augusto von Dentz
185801ce70b0SLuiz Augusto von Dentz /* Instance 0x00 always set local name */
185901ce70b0SLuiz Augusto von Dentz if (instance == 0x00)
186001ce70b0SLuiz Augusto von Dentz return true;
186101ce70b0SLuiz Augusto von Dentz
186201ce70b0SLuiz Augusto von Dentz adv = hci_find_adv_instance(hdev, instance);
186301ce70b0SLuiz Augusto von Dentz if (!adv)
186401ce70b0SLuiz Augusto von Dentz return false;
186501ce70b0SLuiz Augusto von Dentz
186601ce70b0SLuiz Augusto von Dentz if (adv->flags & MGMT_ADV_FLAG_APPEARANCE ||
186701ce70b0SLuiz Augusto von Dentz adv->flags & MGMT_ADV_FLAG_LOCAL_NAME)
186801ce70b0SLuiz Augusto von Dentz return true;
186901ce70b0SLuiz Augusto von Dentz
187001ce70b0SLuiz Augusto von Dentz return adv->scan_rsp_len ? true : false;
187101ce70b0SLuiz Augusto von Dentz }
187201ce70b0SLuiz Augusto von Dentz
187301ce70b0SLuiz Augusto von Dentz /* This function requires the caller holds hdev->lock */
hci_adv_monitors_clear(struct hci_dev * hdev)1874e5e1e7fdSMiao-chen Chou void hci_adv_monitors_clear(struct hci_dev *hdev)
1875e5e1e7fdSMiao-chen Chou {
1876b139553dSMiao-chen Chou struct adv_monitor *monitor;
1877b139553dSMiao-chen Chou int handle;
1878b139553dSMiao-chen Chou
1879b139553dSMiao-chen Chou idr_for_each_entry(&hdev->adv_monitors_idr, monitor, handle)
188066bd095aSArchie Pusaka hci_free_adv_monitor(hdev, monitor);
1881b139553dSMiao-chen Chou
1882e5e1e7fdSMiao-chen Chou idr_destroy(&hdev->adv_monitors_idr);
1883e5e1e7fdSMiao-chen Chou }
1884e5e1e7fdSMiao-chen Chou
188566bd095aSArchie Pusaka /* Frees the monitor structure and do some bookkeepings.
188666bd095aSArchie Pusaka * This function requires the caller holds hdev->lock.
188766bd095aSArchie Pusaka */
hci_free_adv_monitor(struct hci_dev * hdev,struct adv_monitor * monitor)188866bd095aSArchie Pusaka void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
1889b139553dSMiao-chen Chou {
1890b139553dSMiao-chen Chou struct adv_pattern *pattern;
1891b139553dSMiao-chen Chou struct adv_pattern *tmp;
1892b139553dSMiao-chen Chou
1893b139553dSMiao-chen Chou if (!monitor)
1894b139553dSMiao-chen Chou return;
1895b139553dSMiao-chen Chou
189666bd095aSArchie Pusaka list_for_each_entry_safe(pattern, tmp, &monitor->patterns, list) {
189766bd095aSArchie Pusaka list_del(&pattern->list);
1898b139553dSMiao-chen Chou kfree(pattern);
189966bd095aSArchie Pusaka }
190066bd095aSArchie Pusaka
190166bd095aSArchie Pusaka if (monitor->handle)
190266bd095aSArchie Pusaka idr_remove(&hdev->adv_monitors_idr, monitor->handle);
190366bd095aSArchie Pusaka
190466bd095aSArchie Pusaka if (monitor->state != ADV_MONITOR_STATE_NOT_REGISTERED) {
190566bd095aSArchie Pusaka hdev->adv_monitors_cnt--;
190666bd095aSArchie Pusaka mgmt_adv_monitor_removed(hdev, monitor->handle);
190766bd095aSArchie Pusaka }
1908b139553dSMiao-chen Chou
1909b139553dSMiao-chen Chou kfree(monitor);
1910b139553dSMiao-chen Chou }
1911b139553dSMiao-chen Chou
1912a2a4dedfSArchie Pusaka /* Assigns handle to a monitor, and if offloading is supported and power is on,
1913a2a4dedfSArchie Pusaka * also attempts to forward the request to the controller.
1914b747a836SManish Mandlik * This function requires the caller holds hci_req_sync_lock.
1915a2a4dedfSArchie Pusaka */
hci_add_adv_monitor(struct hci_dev * hdev,struct adv_monitor * monitor)1916b747a836SManish Mandlik int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
1917b139553dSMiao-chen Chou {
1918b139553dSMiao-chen Chou int min, max, handle;
1919b747a836SManish Mandlik int status = 0;
1920b139553dSMiao-chen Chou
1921b747a836SManish Mandlik if (!monitor)
1922b747a836SManish Mandlik return -EINVAL;
1923a2a4dedfSArchie Pusaka
1924b747a836SManish Mandlik hci_dev_lock(hdev);
1925b139553dSMiao-chen Chou
1926b139553dSMiao-chen Chou min = HCI_MIN_ADV_MONITOR_HANDLE;
1927b139553dSMiao-chen Chou max = HCI_MIN_ADV_MONITOR_HANDLE + HCI_MAX_ADV_MONITOR_NUM_HANDLES;
1928b139553dSMiao-chen Chou handle = idr_alloc(&hdev->adv_monitors_idr, monitor, min, max,
1929b139553dSMiao-chen Chou GFP_KERNEL);
1930b747a836SManish Mandlik
1931b747a836SManish Mandlik hci_dev_unlock(hdev);
1932b747a836SManish Mandlik
1933b747a836SManish Mandlik if (handle < 0)
1934b747a836SManish Mandlik return handle;
1935b139553dSMiao-chen Chou
1936b139553dSMiao-chen Chou monitor->handle = handle;
19378208f5a9SMiao-chen Chou
1938a2a4dedfSArchie Pusaka if (!hdev_is_powered(hdev))
1939b747a836SManish Mandlik return status;
19408208f5a9SMiao-chen Chou
1941a2a4dedfSArchie Pusaka switch (hci_get_adv_monitor_offload_ext(hdev)) {
1942a2a4dedfSArchie Pusaka case HCI_ADV_MONITOR_EXT_NONE:
19436f55eea1SDouglas Anderson bt_dev_dbg(hdev, "add monitor %d status %d",
1944b747a836SManish Mandlik monitor->handle, status);
1945a2a4dedfSArchie Pusaka /* Message was not forwarded to controller - not an error */
1946b747a836SManish Mandlik break;
1947b747a836SManish Mandlik
1948a2a4dedfSArchie Pusaka case HCI_ADV_MONITOR_EXT_MSFT:
1949b747a836SManish Mandlik status = msft_add_monitor_pattern(hdev, monitor);
19506f55eea1SDouglas Anderson bt_dev_dbg(hdev, "add monitor %d msft status %d",
1951a2bcd2b6SManish Mandlik handle, status);
1952a2a4dedfSArchie Pusaka break;
1953a2a4dedfSArchie Pusaka }
1954a2a4dedfSArchie Pusaka
1955b747a836SManish Mandlik return status;
1956b139553dSMiao-chen Chou }
1957b139553dSMiao-chen Chou
195866bd095aSArchie Pusaka /* Attempts to tell the controller and free the monitor. If somehow the
195966bd095aSArchie Pusaka * controller doesn't have a corresponding handle, remove anyway.
19607cf5c297SManish Mandlik * This function requires the caller holds hci_req_sync_lock.
196166bd095aSArchie Pusaka */
hci_remove_adv_monitor(struct hci_dev * hdev,struct adv_monitor * monitor)19627cf5c297SManish Mandlik static int hci_remove_adv_monitor(struct hci_dev *hdev,
19637cf5c297SManish Mandlik struct adv_monitor *monitor)
1964bd2fbc6cSMiao-chen Chou {
19657cf5c297SManish Mandlik int status = 0;
1966de6dfcefSDouglas Anderson int handle;
1967bd2fbc6cSMiao-chen Chou
196866bd095aSArchie Pusaka switch (hci_get_adv_monitor_offload_ext(hdev)) {
196966bd095aSArchie Pusaka case HCI_ADV_MONITOR_EXT_NONE: /* also goes here when powered off */
19706f55eea1SDouglas Anderson bt_dev_dbg(hdev, "remove monitor %d status %d",
19717cf5c297SManish Mandlik monitor->handle, status);
197266bd095aSArchie Pusaka goto free_monitor;
19737cf5c297SManish Mandlik
197466bd095aSArchie Pusaka case HCI_ADV_MONITOR_EXT_MSFT:
1975de6dfcefSDouglas Anderson handle = monitor->handle;
19767cf5c297SManish Mandlik status = msft_remove_monitor(hdev, monitor);
19776f55eea1SDouglas Anderson bt_dev_dbg(hdev, "remove monitor %d msft status %d",
19786f55eea1SDouglas Anderson handle, status);
197966bd095aSArchie Pusaka break;
1980bd2fbc6cSMiao-chen Chou }
1981bd2fbc6cSMiao-chen Chou
198266bd095aSArchie Pusaka /* In case no matching handle registered, just free the monitor */
19837cf5c297SManish Mandlik if (status == -ENOENT)
198466bd095aSArchie Pusaka goto free_monitor;
1985bd2fbc6cSMiao-chen Chou
19867cf5c297SManish Mandlik return status;
1987bd2fbc6cSMiao-chen Chou
198866bd095aSArchie Pusaka free_monitor:
19897cf5c297SManish Mandlik if (status == -ENOENT)
199066bd095aSArchie Pusaka bt_dev_warn(hdev, "Removing monitor with no matching handle %d",
199166bd095aSArchie Pusaka monitor->handle);
199266bd095aSArchie Pusaka hci_free_adv_monitor(hdev, monitor);
199366bd095aSArchie Pusaka
19947cf5c297SManish Mandlik return status;
1995bd2fbc6cSMiao-chen Chou }
1996bd2fbc6cSMiao-chen Chou
19977cf5c297SManish Mandlik /* This function requires the caller holds hci_req_sync_lock */
hci_remove_single_adv_monitor(struct hci_dev * hdev,u16 handle)19987cf5c297SManish Mandlik int hci_remove_single_adv_monitor(struct hci_dev *hdev, u16 handle)
199966bd095aSArchie Pusaka {
200066bd095aSArchie Pusaka struct adv_monitor *monitor = idr_find(&hdev->adv_monitors_idr, handle);
200166bd095aSArchie Pusaka
20027cf5c297SManish Mandlik if (!monitor)
20037cf5c297SManish Mandlik return -EINVAL;
20047cf5c297SManish Mandlik
20057cf5c297SManish Mandlik return hci_remove_adv_monitor(hdev, monitor);
200666bd095aSArchie Pusaka }
200766bd095aSArchie Pusaka
20087cf5c297SManish Mandlik /* This function requires the caller holds hci_req_sync_lock */
hci_remove_all_adv_monitor(struct hci_dev * hdev)20097cf5c297SManish Mandlik int hci_remove_all_adv_monitor(struct hci_dev *hdev)
201066bd095aSArchie Pusaka {
201166bd095aSArchie Pusaka struct adv_monitor *monitor;
201266bd095aSArchie Pusaka int idr_next_id = 0;
20137cf5c297SManish Mandlik int status = 0;
201466bd095aSArchie Pusaka
20157cf5c297SManish Mandlik while (1) {
201666bd095aSArchie Pusaka monitor = idr_get_next(&hdev->adv_monitors_idr, &idr_next_id);
201766bd095aSArchie Pusaka if (!monitor)
201866bd095aSArchie Pusaka break;
201966bd095aSArchie Pusaka
20207cf5c297SManish Mandlik status = hci_remove_adv_monitor(hdev, monitor);
20217cf5c297SManish Mandlik if (status)
20227cf5c297SManish Mandlik return status;
202366bd095aSArchie Pusaka
20247cf5c297SManish Mandlik idr_next_id++;
202566bd095aSArchie Pusaka }
202666bd095aSArchie Pusaka
20277cf5c297SManish Mandlik return status;
2028bd2fbc6cSMiao-chen Chou }
2029bd2fbc6cSMiao-chen Chou
20308208f5a9SMiao-chen Chou /* This function requires the caller holds hdev->lock */
hci_is_adv_monitoring(struct hci_dev * hdev)20318208f5a9SMiao-chen Chou bool hci_is_adv_monitoring(struct hci_dev *hdev)
20328208f5a9SMiao-chen Chou {
20338208f5a9SMiao-chen Chou return !idr_is_empty(&hdev->adv_monitors_idr);
20348208f5a9SMiao-chen Chou }
20358208f5a9SMiao-chen Chou
hci_get_adv_monitor_offload_ext(struct hci_dev * hdev)2036a2a4dedfSArchie Pusaka int hci_get_adv_monitor_offload_ext(struct hci_dev *hdev)
2037a2a4dedfSArchie Pusaka {
2038a2a4dedfSArchie Pusaka if (msft_monitor_supported(hdev))
2039a2a4dedfSArchie Pusaka return HCI_ADV_MONITOR_EXT_MSFT;
2040a2a4dedfSArchie Pusaka
2041a2a4dedfSArchie Pusaka return HCI_ADV_MONITOR_EXT_NONE;
2042a2a4dedfSArchie Pusaka }
2043a2a4dedfSArchie Pusaka
hci_bdaddr_list_lookup(struct list_head * bdaddr_list,bdaddr_t * bdaddr,u8 type)2044dcc36c16SJohan Hedberg struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list,
2045b9ee0a78SMarcel Holtmann bdaddr_t *bdaddr, u8 type)
2046b2a66aadSAntti Julku {
2047b2a66aadSAntti Julku struct bdaddr_list *b;
2048b2a66aadSAntti Julku
2049dcc36c16SJohan Hedberg list_for_each_entry(b, bdaddr_list, list) {
2050b9ee0a78SMarcel Holtmann if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
2051b2a66aadSAntti Julku return b;
2052b9ee0a78SMarcel Holtmann }
2053b2a66aadSAntti Julku
2054b2a66aadSAntti Julku return NULL;
2055b2a66aadSAntti Julku }
2056b2a66aadSAntti Julku
hci_bdaddr_list_lookup_with_irk(struct list_head * bdaddr_list,bdaddr_t * bdaddr,u8 type)2057b950aa88SAnkit Navik struct bdaddr_list_with_irk *hci_bdaddr_list_lookup_with_irk(
2058b950aa88SAnkit Navik struct list_head *bdaddr_list, bdaddr_t *bdaddr,
2059b950aa88SAnkit Navik u8 type)
2060b950aa88SAnkit Navik {
2061b950aa88SAnkit Navik struct bdaddr_list_with_irk *b;
2062b950aa88SAnkit Navik
2063b950aa88SAnkit Navik list_for_each_entry(b, bdaddr_list, list) {
2064b950aa88SAnkit Navik if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
2065b950aa88SAnkit Navik return b;
2066b950aa88SAnkit Navik }
2067b950aa88SAnkit Navik
2068b950aa88SAnkit Navik return NULL;
2069b950aa88SAnkit Navik }
2070b950aa88SAnkit Navik
20718baaa403SAbhishek Pandit-Subedi struct bdaddr_list_with_flags *
hci_bdaddr_list_lookup_with_flags(struct list_head * bdaddr_list,bdaddr_t * bdaddr,u8 type)20728baaa403SAbhishek Pandit-Subedi hci_bdaddr_list_lookup_with_flags(struct list_head *bdaddr_list,
20738baaa403SAbhishek Pandit-Subedi bdaddr_t *bdaddr, u8 type)
20748baaa403SAbhishek Pandit-Subedi {
20758baaa403SAbhishek Pandit-Subedi struct bdaddr_list_with_flags *b;
20768baaa403SAbhishek Pandit-Subedi
20778baaa403SAbhishek Pandit-Subedi list_for_each_entry(b, bdaddr_list, list) {
20788baaa403SAbhishek Pandit-Subedi if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
20798baaa403SAbhishek Pandit-Subedi return b;
20808baaa403SAbhishek Pandit-Subedi }
20818baaa403SAbhishek Pandit-Subedi
20828baaa403SAbhishek Pandit-Subedi return NULL;
20838baaa403SAbhishek Pandit-Subedi }
20848baaa403SAbhishek Pandit-Subedi
hci_bdaddr_list_clear(struct list_head * bdaddr_list)2085dcc36c16SJohan Hedberg void hci_bdaddr_list_clear(struct list_head *bdaddr_list)
2086b2a66aadSAntti Julku {
20877eb7404fSGeliang Tang struct bdaddr_list *b, *n;
2088b2a66aadSAntti Julku
20897eb7404fSGeliang Tang list_for_each_entry_safe(b, n, bdaddr_list, list) {
20907eb7404fSGeliang Tang list_del(&b->list);
2091b2a66aadSAntti Julku kfree(b);
2092b2a66aadSAntti Julku }
2093b2a66aadSAntti Julku }
2094b2a66aadSAntti Julku
hci_bdaddr_list_add(struct list_head * list,bdaddr_t * bdaddr,u8 type)2095dcc36c16SJohan Hedberg int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type)
2096b2a66aadSAntti Julku {
2097b2a66aadSAntti Julku struct bdaddr_list *entry;
2098b2a66aadSAntti Julku
2099b9ee0a78SMarcel Holtmann if (!bacmp(bdaddr, BDADDR_ANY))
2100b2a66aadSAntti Julku return -EBADF;
2101b2a66aadSAntti Julku
2102dcc36c16SJohan Hedberg if (hci_bdaddr_list_lookup(list, bdaddr, type))
21035e762444SAntti Julku return -EEXIST;
2104b2a66aadSAntti Julku
210527f70f3eSJohan Hedberg entry = kzalloc(sizeof(*entry), GFP_KERNEL);
21065e762444SAntti Julku if (!entry)
21075e762444SAntti Julku return -ENOMEM;
2108b2a66aadSAntti Julku
2109b2a66aadSAntti Julku bacpy(&entry->bdaddr, bdaddr);
2110b9ee0a78SMarcel Holtmann entry->bdaddr_type = type;
2111b2a66aadSAntti Julku
2112dcc36c16SJohan Hedberg list_add(&entry->list, list);
2113b2a66aadSAntti Julku
21142a8357f2SJohan Hedberg return 0;
2115b2a66aadSAntti Julku }
2116b2a66aadSAntti Julku
hci_bdaddr_list_add_with_irk(struct list_head * list,bdaddr_t * bdaddr,u8 type,u8 * peer_irk,u8 * local_irk)2117b950aa88SAnkit Navik int hci_bdaddr_list_add_with_irk(struct list_head *list, bdaddr_t *bdaddr,
2118b950aa88SAnkit Navik u8 type, u8 *peer_irk, u8 *local_irk)
2119b950aa88SAnkit Navik {
2120b950aa88SAnkit Navik struct bdaddr_list_with_irk *entry;
2121b950aa88SAnkit Navik
2122b950aa88SAnkit Navik if (!bacmp(bdaddr, BDADDR_ANY))
2123b950aa88SAnkit Navik return -EBADF;
2124b950aa88SAnkit Navik
2125b950aa88SAnkit Navik if (hci_bdaddr_list_lookup(list, bdaddr, type))
2126b950aa88SAnkit Navik return -EEXIST;
2127b950aa88SAnkit Navik
2128b950aa88SAnkit Navik entry = kzalloc(sizeof(*entry), GFP_KERNEL);
2129b950aa88SAnkit Navik if (!entry)
2130b950aa88SAnkit Navik return -ENOMEM;
2131b950aa88SAnkit Navik
2132b950aa88SAnkit Navik bacpy(&entry->bdaddr, bdaddr);
2133b950aa88SAnkit Navik entry->bdaddr_type = type;
2134b950aa88SAnkit Navik
2135b950aa88SAnkit Navik if (peer_irk)
2136b950aa88SAnkit Navik memcpy(entry->peer_irk, peer_irk, 16);
2137b950aa88SAnkit Navik
2138b950aa88SAnkit Navik if (local_irk)
2139b950aa88SAnkit Navik memcpy(entry->local_irk, local_irk, 16);
2140b950aa88SAnkit Navik
2141b950aa88SAnkit Navik list_add(&entry->list, list);
2142b950aa88SAnkit Navik
2143b950aa88SAnkit Navik return 0;
2144b950aa88SAnkit Navik }
2145b950aa88SAnkit Navik
hci_bdaddr_list_add_with_flags(struct list_head * list,bdaddr_t * bdaddr,u8 type,u32 flags)21468baaa403SAbhishek Pandit-Subedi int hci_bdaddr_list_add_with_flags(struct list_head *list, bdaddr_t *bdaddr,
21478baaa403SAbhishek Pandit-Subedi u8 type, u32 flags)
21488baaa403SAbhishek Pandit-Subedi {
21498baaa403SAbhishek Pandit-Subedi struct bdaddr_list_with_flags *entry;
21508baaa403SAbhishek Pandit-Subedi
21518baaa403SAbhishek Pandit-Subedi if (!bacmp(bdaddr, BDADDR_ANY))
21528baaa403SAbhishek Pandit-Subedi return -EBADF;
21538baaa403SAbhishek Pandit-Subedi
21548baaa403SAbhishek Pandit-Subedi if (hci_bdaddr_list_lookup(list, bdaddr, type))
21558baaa403SAbhishek Pandit-Subedi return -EEXIST;
21568baaa403SAbhishek Pandit-Subedi
21578baaa403SAbhishek Pandit-Subedi entry = kzalloc(sizeof(*entry), GFP_KERNEL);
21588baaa403SAbhishek Pandit-Subedi if (!entry)
21598baaa403SAbhishek Pandit-Subedi return -ENOMEM;
21608baaa403SAbhishek Pandit-Subedi
21618baaa403SAbhishek Pandit-Subedi bacpy(&entry->bdaddr, bdaddr);
21628baaa403SAbhishek Pandit-Subedi entry->bdaddr_type = type;
2163e1cff700SLinus Torvalds entry->flags = flags;
21648baaa403SAbhishek Pandit-Subedi
21658baaa403SAbhishek Pandit-Subedi list_add(&entry->list, list);
21668baaa403SAbhishek Pandit-Subedi
21678baaa403SAbhishek Pandit-Subedi return 0;
21688baaa403SAbhishek Pandit-Subedi }
21698baaa403SAbhishek Pandit-Subedi
hci_bdaddr_list_del(struct list_head * list,bdaddr_t * bdaddr,u8 type)2170dcc36c16SJohan Hedberg int hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type)
2171b2a66aadSAntti Julku {
2172b2a66aadSAntti Julku struct bdaddr_list *entry;
2173b2a66aadSAntti Julku
217435f7498aSJohan Hedberg if (!bacmp(bdaddr, BDADDR_ANY)) {
2175dcc36c16SJohan Hedberg hci_bdaddr_list_clear(list);
217635f7498aSJohan Hedberg return 0;
217735f7498aSJohan Hedberg }
2178b2a66aadSAntti Julku
2179dcc36c16SJohan Hedberg entry = hci_bdaddr_list_lookup(list, bdaddr, type);
2180d2ab0ac1SMarcel Holtmann if (!entry)
2181d2ab0ac1SMarcel Holtmann return -ENOENT;
2182d2ab0ac1SMarcel Holtmann
2183d2ab0ac1SMarcel Holtmann list_del(&entry->list);
2184d2ab0ac1SMarcel Holtmann kfree(entry);
2185d2ab0ac1SMarcel Holtmann
2186d2ab0ac1SMarcel Holtmann return 0;
2187d2ab0ac1SMarcel Holtmann }
2188d2ab0ac1SMarcel Holtmann
hci_bdaddr_list_del_with_irk(struct list_head * list,bdaddr_t * bdaddr,u8 type)2189b950aa88SAnkit Navik int hci_bdaddr_list_del_with_irk(struct list_head *list, bdaddr_t *bdaddr,
2190b950aa88SAnkit Navik u8 type)
2191b950aa88SAnkit Navik {
2192b950aa88SAnkit Navik struct bdaddr_list_with_irk *entry;
2193b950aa88SAnkit Navik
2194b950aa88SAnkit Navik if (!bacmp(bdaddr, BDADDR_ANY)) {
2195b950aa88SAnkit Navik hci_bdaddr_list_clear(list);
2196b950aa88SAnkit Navik return 0;
2197b950aa88SAnkit Navik }
2198b950aa88SAnkit Navik
2199b950aa88SAnkit Navik entry = hci_bdaddr_list_lookup_with_irk(list, bdaddr, type);
2200b950aa88SAnkit Navik if (!entry)
2201b950aa88SAnkit Navik return -ENOENT;
2202b950aa88SAnkit Navik
2203b950aa88SAnkit Navik list_del(&entry->list);
2204b950aa88SAnkit Navik kfree(entry);
2205b950aa88SAnkit Navik
2206b950aa88SAnkit Navik return 0;
2207b950aa88SAnkit Navik }
2208b950aa88SAnkit Navik
hci_bdaddr_list_del_with_flags(struct list_head * list,bdaddr_t * bdaddr,u8 type)22098baaa403SAbhishek Pandit-Subedi int hci_bdaddr_list_del_with_flags(struct list_head *list, bdaddr_t *bdaddr,
22108baaa403SAbhishek Pandit-Subedi u8 type)
22118baaa403SAbhishek Pandit-Subedi {
22128baaa403SAbhishek Pandit-Subedi struct bdaddr_list_with_flags *entry;
22138baaa403SAbhishek Pandit-Subedi
22148baaa403SAbhishek Pandit-Subedi if (!bacmp(bdaddr, BDADDR_ANY)) {
22158baaa403SAbhishek Pandit-Subedi hci_bdaddr_list_clear(list);
22168baaa403SAbhishek Pandit-Subedi return 0;
22178baaa403SAbhishek Pandit-Subedi }
22188baaa403SAbhishek Pandit-Subedi
22198baaa403SAbhishek Pandit-Subedi entry = hci_bdaddr_list_lookup_with_flags(list, bdaddr, type);
22208baaa403SAbhishek Pandit-Subedi if (!entry)
22218baaa403SAbhishek Pandit-Subedi return -ENOENT;
22228baaa403SAbhishek Pandit-Subedi
22238baaa403SAbhishek Pandit-Subedi list_del(&entry->list);
22248baaa403SAbhishek Pandit-Subedi kfree(entry);
22258baaa403SAbhishek Pandit-Subedi
22268baaa403SAbhishek Pandit-Subedi return 0;
22278baaa403SAbhishek Pandit-Subedi }
22288baaa403SAbhishek Pandit-Subedi
222915819a70SAndre Guedes /* This function requires the caller holds hdev->lock */
hci_conn_params_lookup(struct hci_dev * hdev,bdaddr_t * addr,u8 addr_type)223015819a70SAndre Guedes struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
223115819a70SAndre Guedes bdaddr_t *addr, u8 addr_type)
223215819a70SAndre Guedes {
223315819a70SAndre Guedes struct hci_conn_params *params;
223415819a70SAndre Guedes
223515819a70SAndre Guedes list_for_each_entry(params, &hdev->le_conn_params, list) {
223615819a70SAndre Guedes if (bacmp(¶ms->addr, addr) == 0 &&
223715819a70SAndre Guedes params->addr_type == addr_type) {
223815819a70SAndre Guedes return params;
223915819a70SAndre Guedes }
224015819a70SAndre Guedes }
224115819a70SAndre Guedes
224215819a70SAndre Guedes return NULL;
224315819a70SAndre Guedes }
224415819a70SAndre Guedes
2245195ef75eSPauli Virtanen /* This function requires the caller holds hdev->lock or rcu_read_lock */
hci_pend_le_action_lookup(struct list_head * list,bdaddr_t * addr,u8 addr_type)2246501f8827SJohan Hedberg struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
22474b10966fSMarcel Holtmann bdaddr_t *addr, u8 addr_type)
2248a9b0a04cSAndre Guedes {
2249912b42efSJohan Hedberg struct hci_conn_params *param;
2250a9b0a04cSAndre Guedes
2251195ef75eSPauli Virtanen rcu_read_lock();
2252195ef75eSPauli Virtanen
2253195ef75eSPauli Virtanen list_for_each_entry_rcu(param, list, action) {
2254912b42efSJohan Hedberg if (bacmp(¶m->addr, addr) == 0 &&
2255195ef75eSPauli Virtanen param->addr_type == addr_type) {
2256195ef75eSPauli Virtanen rcu_read_unlock();
2257912b42efSJohan Hedberg return param;
22584b10966fSMarcel Holtmann }
2259195ef75eSPauli Virtanen }
2260195ef75eSPauli Virtanen
2261195ef75eSPauli Virtanen rcu_read_unlock();
22624b10966fSMarcel Holtmann
22634b10966fSMarcel Holtmann return NULL;
2264a9b0a04cSAndre Guedes }
2265a9b0a04cSAndre Guedes
226615819a70SAndre Guedes /* This function requires the caller holds hdev->lock */
hci_pend_le_list_del_init(struct hci_conn_params * param)2267195ef75eSPauli Virtanen void hci_pend_le_list_del_init(struct hci_conn_params *param)
2268195ef75eSPauli Virtanen {
2269195ef75eSPauli Virtanen if (list_empty(¶m->action))
2270195ef75eSPauli Virtanen return;
2271195ef75eSPauli Virtanen
2272195ef75eSPauli Virtanen list_del_rcu(¶m->action);
2273195ef75eSPauli Virtanen synchronize_rcu();
2274195ef75eSPauli Virtanen INIT_LIST_HEAD(¶m->action);
2275195ef75eSPauli Virtanen }
2276195ef75eSPauli Virtanen
2277195ef75eSPauli Virtanen /* This function requires the caller holds hdev->lock */
hci_pend_le_list_add(struct hci_conn_params * param,struct list_head * list)2278195ef75eSPauli Virtanen void hci_pend_le_list_add(struct hci_conn_params *param,
2279195ef75eSPauli Virtanen struct list_head *list)
2280195ef75eSPauli Virtanen {
2281195ef75eSPauli Virtanen list_add_rcu(¶m->action, list);
2282195ef75eSPauli Virtanen }
2283195ef75eSPauli Virtanen
2284195ef75eSPauli Virtanen /* This function requires the caller holds hdev->lock */
hci_conn_params_add(struct hci_dev * hdev,bdaddr_t * addr,u8 addr_type)228551d167c0SMarcel Holtmann struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
228651d167c0SMarcel Holtmann bdaddr_t *addr, u8 addr_type)
228715819a70SAndre Guedes {
228815819a70SAndre Guedes struct hci_conn_params *params;
228915819a70SAndre Guedes
229015819a70SAndre Guedes params = hci_conn_params_lookup(hdev, addr, addr_type);
2291cef952ceSAndre Guedes if (params)
229251d167c0SMarcel Holtmann return params;
229315819a70SAndre Guedes
229415819a70SAndre Guedes params = kzalloc(sizeof(*params), GFP_KERNEL);
229515819a70SAndre Guedes if (!params) {
22962064ee33SMarcel Holtmann bt_dev_err(hdev, "out of memory");
229751d167c0SMarcel Holtmann return NULL;
229815819a70SAndre Guedes }
229915819a70SAndre Guedes
230015819a70SAndre Guedes bacpy(¶ms->addr, addr);
230115819a70SAndre Guedes params->addr_type = addr_type;
2302cef952ceSAndre Guedes
2303cef952ceSAndre Guedes list_add(¶ms->list, &hdev->le_conn_params);
230493450c75SJohan Hedberg INIT_LIST_HEAD(¶ms->action);
2305cef952ceSAndre Guedes
2306bf5b3c8bSMarcel Holtmann params->conn_min_interval = hdev->le_conn_min_interval;
2307bf5b3c8bSMarcel Holtmann params->conn_max_interval = hdev->le_conn_max_interval;
2308bf5b3c8bSMarcel Holtmann params->conn_latency = hdev->le_conn_latency;
2309bf5b3c8bSMarcel Holtmann params->supervision_timeout = hdev->le_supv_timeout;
2310bf5b3c8bSMarcel Holtmann params->auto_connect = HCI_AUTO_CONN_DISABLED;
2311bf5b3c8bSMarcel Holtmann
2312bf5b3c8bSMarcel Holtmann BT_DBG("addr %pMR (type %u)", addr, addr_type);
2313bf5b3c8bSMarcel Holtmann
231451d167c0SMarcel Holtmann return params;
2315bf5b3c8bSMarcel Holtmann }
2316bf5b3c8bSMarcel Holtmann
hci_conn_params_free(struct hci_conn_params * params)2317195ef75eSPauli Virtanen void hci_conn_params_free(struct hci_conn_params *params)
2318f6c63249SJohan Hedberg {
2319195ef75eSPauli Virtanen hci_pend_le_list_del_init(params);
2320195ef75eSPauli Virtanen
2321f6c63249SJohan Hedberg if (params->conn) {
2322f6c63249SJohan Hedberg hci_conn_drop(params->conn);
2323f6c63249SJohan Hedberg hci_conn_put(params->conn);
2324f6c63249SJohan Hedberg }
2325f6c63249SJohan Hedberg
2326f6c63249SJohan Hedberg list_del(¶ms->list);
2327f6c63249SJohan Hedberg kfree(params);
2328f6c63249SJohan Hedberg }
2329f6c63249SJohan Hedberg
233015819a70SAndre Guedes /* This function requires the caller holds hdev->lock */
hci_conn_params_del(struct hci_dev * hdev,bdaddr_t * addr,u8 addr_type)233115819a70SAndre Guedes void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
233215819a70SAndre Guedes {
233315819a70SAndre Guedes struct hci_conn_params *params;
233415819a70SAndre Guedes
233515819a70SAndre Guedes params = hci_conn_params_lookup(hdev, addr, addr_type);
233615819a70SAndre Guedes if (!params)
233715819a70SAndre Guedes return;
233815819a70SAndre Guedes
2339f6c63249SJohan Hedberg hci_conn_params_free(params);
234015819a70SAndre Guedes
23415bee2fd6SLuiz Augusto von Dentz hci_update_passive_scan(hdev);
234295305baaSJohan Hedberg
234315819a70SAndre Guedes BT_DBG("addr %pMR (type %u)", addr, addr_type);
234415819a70SAndre Guedes }
234515819a70SAndre Guedes
234615819a70SAndre Guedes /* This function requires the caller holds hdev->lock */
hci_conn_params_clear_disabled(struct hci_dev * hdev)234755af49a8SJohan Hedberg void hci_conn_params_clear_disabled(struct hci_dev *hdev)
234815819a70SAndre Guedes {
234915819a70SAndre Guedes struct hci_conn_params *params, *tmp;
235015819a70SAndre Guedes
235115819a70SAndre Guedes list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
235255af49a8SJohan Hedberg if (params->auto_connect != HCI_AUTO_CONN_DISABLED)
235355af49a8SJohan Hedberg continue;
2354f75113a2SJakub Pawlowski
235591641b79SZheng Yongjun /* If trying to establish one time connection to disabled
2356f75113a2SJakub Pawlowski * device, leave the params, but mark them as just once.
2357f75113a2SJakub Pawlowski */
2358f75113a2SJakub Pawlowski if (params->explicit_connect) {
2359f75113a2SJakub Pawlowski params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
2360f75113a2SJakub Pawlowski continue;
2361f75113a2SJakub Pawlowski }
2362f75113a2SJakub Pawlowski
2363195ef75eSPauli Virtanen hci_conn_params_free(params);
236415819a70SAndre Guedes }
236515819a70SAndre Guedes
236655af49a8SJohan Hedberg BT_DBG("All LE disabled connection parameters were removed");
236755af49a8SJohan Hedberg }
236855af49a8SJohan Hedberg
236955af49a8SJohan Hedberg /* This function requires the caller holds hdev->lock */
hci_conn_params_clear_all(struct hci_dev * hdev)2370030e7f81SJohan Hedberg static void hci_conn_params_clear_all(struct hci_dev *hdev)
237115819a70SAndre Guedes {
237215819a70SAndre Guedes struct hci_conn_params *params, *tmp;
237315819a70SAndre Guedes
2374f6c63249SJohan Hedberg list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list)
2375f6c63249SJohan Hedberg hci_conn_params_free(params);
237615819a70SAndre Guedes
237715819a70SAndre Guedes BT_DBG("All LE connection parameters were removed");
237815819a70SAndre Guedes }
237915819a70SAndre Guedes
2380a1f4c318SJohan Hedberg /* Copy the Identity Address of the controller.
2381a1f4c318SJohan Hedberg *
2382a1f4c318SJohan Hedberg * If the controller has a public BD_ADDR, then by default use that one.
2383a1f4c318SJohan Hedberg * If this is a LE only controller without a public address, default to
2384a1f4c318SJohan Hedberg * the static random address.
2385a1f4c318SJohan Hedberg *
2386a1f4c318SJohan Hedberg * For debugging purposes it is possible to force controllers with a
2387a1f4c318SJohan Hedberg * public address to use the static random address instead.
238850b5b952SMarcel Holtmann *
238950b5b952SMarcel Holtmann * In case BR/EDR has been disabled on a dual-mode controller and
239050b5b952SMarcel Holtmann * userspace has configured a static address, then that address
239150b5b952SMarcel Holtmann * becomes the identity address instead of the public BR/EDR address.
2392a1f4c318SJohan Hedberg */
hci_copy_identity_address(struct hci_dev * hdev,bdaddr_t * bdaddr,u8 * bdaddr_type)2393a1f4c318SJohan Hedberg void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
2394a1f4c318SJohan Hedberg u8 *bdaddr_type)
2395a1f4c318SJohan Hedberg {
2396b7cb93e5SMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
239750b5b952SMarcel Holtmann !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
2398d7a5a11dSMarcel Holtmann (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
239950b5b952SMarcel Holtmann bacmp(&hdev->static_addr, BDADDR_ANY))) {
2400a1f4c318SJohan Hedberg bacpy(bdaddr, &hdev->static_addr);
2401a1f4c318SJohan Hedberg *bdaddr_type = ADDR_LE_DEV_RANDOM;
2402a1f4c318SJohan Hedberg } else {
2403a1f4c318SJohan Hedberg bacpy(bdaddr, &hdev->bdaddr);
2404a1f4c318SJohan Hedberg *bdaddr_type = ADDR_LE_DEV_PUBLIC;
2405a1f4c318SJohan Hedberg }
2406a1f4c318SJohan Hedberg }
2407a1f4c318SJohan Hedberg
hci_clear_wake_reason(struct hci_dev * hdev)24082f20216cSAbhishek Pandit-Subedi static void hci_clear_wake_reason(struct hci_dev *hdev)
24092f20216cSAbhishek Pandit-Subedi {
24102f20216cSAbhishek Pandit-Subedi hci_dev_lock(hdev);
24112f20216cSAbhishek Pandit-Subedi
24122f20216cSAbhishek Pandit-Subedi hdev->wake_reason = 0;
24132f20216cSAbhishek Pandit-Subedi bacpy(&hdev->wake_addr, BDADDR_ANY);
24142f20216cSAbhishek Pandit-Subedi hdev->wake_addr_type = 0;
24152f20216cSAbhishek Pandit-Subedi
24162f20216cSAbhishek Pandit-Subedi hci_dev_unlock(hdev);
24172f20216cSAbhishek Pandit-Subedi }
24182f20216cSAbhishek Pandit-Subedi
hci_suspend_notifier(struct notifier_block * nb,unsigned long action,void * data)24199952d90eSAbhishek Pandit-Subedi static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
24209952d90eSAbhishek Pandit-Subedi void *data)
24219952d90eSAbhishek Pandit-Subedi {
24229952d90eSAbhishek Pandit-Subedi struct hci_dev *hdev =
24239952d90eSAbhishek Pandit-Subedi container_of(nb, struct hci_dev, suspend_notifier);
24249952d90eSAbhishek Pandit-Subedi int ret = 0;
24259952d90eSAbhishek Pandit-Subedi
24264b8af331SAbhishek Pandit-Subedi /* Userspace has full control of this device. Do nothing. */
24274b8af331SAbhishek Pandit-Subedi if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
24284b8af331SAbhishek Pandit-Subedi return NOTIFY_DONE;
24294b8af331SAbhishek Pandit-Subedi
2430573ebae1SYing Hsu /* To avoid a potential race with hci_unregister_dev. */
2431573ebae1SYing Hsu hci_dev_hold(hdev);
2432573ebae1SYing Hsu
2433e1b77d68SLuiz Augusto von Dentz if (action == PM_SUSPEND_PREPARE)
2434e1b77d68SLuiz Augusto von Dentz ret = hci_suspend_dev(hdev);
2435e1b77d68SLuiz Augusto von Dentz else if (action == PM_POST_SUSPEND)
2436e1b77d68SLuiz Augusto von Dentz ret = hci_resume_dev(hdev);
24379952d90eSAbhishek Pandit-Subedi
2438a9ec8423SAbhishek Pandit-Subedi if (ret)
2439a9ec8423SAbhishek Pandit-Subedi bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d",
2440a9ec8423SAbhishek Pandit-Subedi action, ret);
2441a9ec8423SAbhishek Pandit-Subedi
2442573ebae1SYing Hsu hci_dev_put(hdev);
244324b06572SMax Chou return NOTIFY_DONE;
24449952d90eSAbhishek Pandit-Subedi }
24458731840aSAbhishek Pandit-Subedi
24469be0dab7SDavid Herrmann /* Alloc HCI device */
hci_alloc_dev_priv(int sizeof_priv)24476ec56613STedd Ho-Jeong An struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
24489be0dab7SDavid Herrmann {
24499be0dab7SDavid Herrmann struct hci_dev *hdev;
24506ec56613STedd Ho-Jeong An unsigned int alloc_size;
24519be0dab7SDavid Herrmann
24526ec56613STedd Ho-Jeong An alloc_size = sizeof(*hdev);
24536ec56613STedd Ho-Jeong An if (sizeof_priv) {
24546ec56613STedd Ho-Jeong An /* Fixme: May need ALIGN-ment? */
24556ec56613STedd Ho-Jeong An alloc_size += sizeof_priv;
24566ec56613STedd Ho-Jeong An }
24576ec56613STedd Ho-Jeong An
24586ec56613STedd Ho-Jeong An hdev = kzalloc(alloc_size, GFP_KERNEL);
24599be0dab7SDavid Herrmann if (!hdev)
24609be0dab7SDavid Herrmann return NULL;
24619be0dab7SDavid Herrmann
2462b1b813d4SDavid Herrmann hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
2463b1b813d4SDavid Herrmann hdev->esco_type = (ESCO_HV1);
2464b1b813d4SDavid Herrmann hdev->link_mode = (HCI_LM_ACCEPT);
2465b4cb9fb2SMarcel Holtmann hdev->num_iac = 0x01; /* One IAC support is mandatory */
2466b1b813d4SDavid Herrmann hdev->io_capability = 0x03; /* No Input No Output */
246796c2103aSMarcel Holtmann hdev->manufacturer = 0xffff; /* Default to internal use */
2468bbaf444aSJohan Hedberg hdev->inq_tx_power = HCI_TX_POWER_INVALID;
2469bbaf444aSJohan Hedberg hdev->adv_tx_power = HCI_TX_POWER_INVALID;
2470d2609b34SFlorian Grandel hdev->adv_instance_cnt = 0;
2471d2609b34SFlorian Grandel hdev->cur_adv_instance = 0x00;
24725d900e46SFlorian Grandel hdev->adv_instance_timeout = 0;
2473b1b813d4SDavid Herrmann
2474c4f1f408SHoward Chung hdev->advmon_allowlist_duration = 300;
2475c4f1f408SHoward Chung hdev->advmon_no_filter_duration = 500;
247680af16a3SHoward Chung hdev->enable_advmon_interleave_scan = 0x00; /* Default to disable */
2477c4f1f408SHoward Chung
2478b1b813d4SDavid Herrmann hdev->sniff_max_interval = 800;
2479b1b813d4SDavid Herrmann hdev->sniff_min_interval = 80;
2480b1b813d4SDavid Herrmann
24813f959d46SMarcel Holtmann hdev->le_adv_channel_map = 0x07;
2482628531c9SGeorg Lukas hdev->le_adv_min_interval = 0x0800;
2483628531c9SGeorg Lukas hdev->le_adv_max_interval = 0x0800;
2484bef64738SMarcel Holtmann hdev->le_scan_interval = 0x0060;
2485bef64738SMarcel Holtmann hdev->le_scan_window = 0x0030;
248610873f99SAlain Michaud hdev->le_scan_int_suspend = 0x0400;
248710873f99SAlain Michaud hdev->le_scan_window_suspend = 0x0012;
248810873f99SAlain Michaud hdev->le_scan_int_discovery = DISCOV_LE_SCAN_INT;
248910873f99SAlain Michaud hdev->le_scan_window_discovery = DISCOV_LE_SCAN_WIN;
2490ba29d036SMarcel Holtmann hdev->le_scan_int_adv_monitor = 0x0060;
2491ba29d036SMarcel Holtmann hdev->le_scan_window_adv_monitor = 0x0030;
249210873f99SAlain Michaud hdev->le_scan_int_connect = 0x0060;
249310873f99SAlain Michaud hdev->le_scan_window_connect = 0x0060;
2494b48c3b59SJonas Holmberg hdev->le_conn_min_interval = 0x0018;
2495b48c3b59SJonas Holmberg hdev->le_conn_max_interval = 0x0028;
249604fb7d90SMarcel Holtmann hdev->le_conn_latency = 0x0000;
249704fb7d90SMarcel Holtmann hdev->le_supv_timeout = 0x002a;
2498a8e1bfaaSMarcel Holtmann hdev->le_def_tx_len = 0x001b;
2499a8e1bfaaSMarcel Holtmann hdev->le_def_tx_time = 0x0148;
2500a8e1bfaaSMarcel Holtmann hdev->le_max_tx_len = 0x001b;
2501a8e1bfaaSMarcel Holtmann hdev->le_max_tx_time = 0x0148;
2502a8e1bfaaSMarcel Holtmann hdev->le_max_rx_len = 0x001b;
2503a8e1bfaaSMarcel Holtmann hdev->le_max_rx_time = 0x0148;
250430d65e08SMatias Karhumaa hdev->le_max_key_size = SMP_MAX_ENC_KEY_SIZE;
250530d65e08SMatias Karhumaa hdev->le_min_key_size = SMP_MIN_ENC_KEY_SIZE;
25066decb5b4SJaganath Kanakkassery hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M;
25076decb5b4SJaganath Kanakkassery hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M;
25081d0fac2cSLuiz Augusto von Dentz hdev->le_num_of_adv_sets = HCI_MAX_ADV_INSTANCES;
250910873f99SAlain Michaud hdev->def_multi_adv_rotation_duration = HCI_DEFAULT_ADV_DURATION;
251049b020c1SAlain Michaud hdev->def_le_autoconnect_timeout = HCI_LE_AUTOCONN_TIMEOUT;
25117c395ea5SDaniel Winkler hdev->min_le_tx_power = HCI_TX_POWER_INVALID;
25127c395ea5SDaniel Winkler hdev->max_le_tx_power = HCI_TX_POWER_INVALID;
2513bef64738SMarcel Holtmann
2514d6bfd59cSJohan Hedberg hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT;
2515b9a7a61eSLukasz Rymanowski hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT;
251631ad1691SAndrzej Kaczmarek hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE;
251731ad1691SAndrzej Kaczmarek hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE;
2518302975cbSSpoorthi Ravishankar Koppad hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT;
251958a96fc3SMarcel Holtmann hdev->min_enc_key_size = HCI_MIN_ENC_KEY_SIZE;
2520d6bfd59cSJohan Hedberg
252110873f99SAlain Michaud /* default 1.28 sec page scan */
252210873f99SAlain Michaud hdev->def_page_scan_type = PAGE_SCAN_TYPE_STANDARD;
252310873f99SAlain Michaud hdev->def_page_scan_int = 0x0800;
252410873f99SAlain Michaud hdev->def_page_scan_window = 0x0012;
252510873f99SAlain Michaud
2526b1b813d4SDavid Herrmann mutex_init(&hdev->lock);
2527b1b813d4SDavid Herrmann mutex_init(&hdev->req_lock);
2528b1b813d4SDavid Herrmann
252984cb0143SZiyang Xuan ida_init(&hdev->unset_handle_ida);
253084cb0143SZiyang Xuan
2531b338d917SBrian Gix INIT_LIST_HEAD(&hdev->mesh_pending);
2532b1b813d4SDavid Herrmann INIT_LIST_HEAD(&hdev->mgmt_pending);
25333d4f9c00SArchie Pusaka INIT_LIST_HEAD(&hdev->reject_list);
25343d4f9c00SArchie Pusaka INIT_LIST_HEAD(&hdev->accept_list);
2535b1b813d4SDavid Herrmann INIT_LIST_HEAD(&hdev->uuids);
2536b1b813d4SDavid Herrmann INIT_LIST_HEAD(&hdev->link_keys);
2537b1b813d4SDavid Herrmann INIT_LIST_HEAD(&hdev->long_term_keys);
2538970c4e46SJohan Hedberg INIT_LIST_HEAD(&hdev->identity_resolving_keys);
2539b1b813d4SDavid Herrmann INIT_LIST_HEAD(&hdev->remote_oob_data);
25403d4f9c00SArchie Pusaka INIT_LIST_HEAD(&hdev->le_accept_list);
2541cfdb0c2dSAnkit Navik INIT_LIST_HEAD(&hdev->le_resolv_list);
254215819a70SAndre Guedes INIT_LIST_HEAD(&hdev->le_conn_params);
254377a77a30SAndre Guedes INIT_LIST_HEAD(&hdev->pend_le_conns);
254466f8455aSJohan Hedberg INIT_LIST_HEAD(&hdev->pend_le_reports);
25456b536b5eSAndrei Emeltchenko INIT_LIST_HEAD(&hdev->conn_hash.list);
2546d2609b34SFlorian Grandel INIT_LIST_HEAD(&hdev->adv_instances);
2547600a8749SAlain Michaud INIT_LIST_HEAD(&hdev->blocked_keys);
25483368aa35SManish Mandlik INIT_LIST_HEAD(&hdev->monitored_devices);
2549b1b813d4SDavid Herrmann
25508961987fSKiran K INIT_LIST_HEAD(&hdev->local_codecs);
2551b1b813d4SDavid Herrmann INIT_WORK(&hdev->rx_work, hci_rx_work);
2552b1b813d4SDavid Herrmann INIT_WORK(&hdev->cmd_work, hci_cmd_work);
2553b1b813d4SDavid Herrmann INIT_WORK(&hdev->tx_work, hci_tx_work);
2554b1b813d4SDavid Herrmann INIT_WORK(&hdev->power_on, hci_power_on);
2555c7741d16SMarcel Holtmann INIT_WORK(&hdev->error_reset, hci_error_reset);
2556b1b813d4SDavid Herrmann
25576a98e383SMarcel Holtmann hci_cmd_sync_init(hdev);
25586a98e383SMarcel Holtmann
2559b1b813d4SDavid Herrmann INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
2560b1b813d4SDavid Herrmann
2561b1b813d4SDavid Herrmann skb_queue_head_init(&hdev->rx_q);
2562b1b813d4SDavid Herrmann skb_queue_head_init(&hdev->cmd_q);
2563b1b813d4SDavid Herrmann skb_queue_head_init(&hdev->raw_q);
2564b1b813d4SDavid Herrmann
2565b1b813d4SDavid Herrmann init_waitqueue_head(&hdev->req_wait_q);
2566b1b813d4SDavid Herrmann
256765cc2b49SMarcel Holtmann INIT_DELAYED_WORK(&hdev->cmd_timer, hci_cmd_timeout);
2568de75cd0dSManish Mandlik INIT_DELAYED_WORK(&hdev->ncmd_timer, hci_ncmd_timeout);
2569b1b813d4SDavid Herrmann
25709695ef87SAbhishek Pandit-Subedi hci_devcd_setup(hdev);
25715fc16cc4SJohan Hedberg hci_request_setup(hdev);
25725fc16cc4SJohan Hedberg
2573b1b813d4SDavid Herrmann hci_init_sysfs(hdev);
2574b1b813d4SDavid Herrmann discovery_init(hdev);
25759be0dab7SDavid Herrmann
25769be0dab7SDavid Herrmann return hdev;
25779be0dab7SDavid Herrmann }
25786ec56613STedd Ho-Jeong An EXPORT_SYMBOL(hci_alloc_dev_priv);
25799be0dab7SDavid Herrmann
25809be0dab7SDavid Herrmann /* Free HCI device */
hci_free_dev(struct hci_dev * hdev)25819be0dab7SDavid Herrmann void hci_free_dev(struct hci_dev *hdev)
25829be0dab7SDavid Herrmann {
25839be0dab7SDavid Herrmann /* will free via device release */
25849be0dab7SDavid Herrmann put_device(&hdev->dev);
25859be0dab7SDavid Herrmann }
25869be0dab7SDavid Herrmann EXPORT_SYMBOL(hci_free_dev);
25879be0dab7SDavid Herrmann
25881da177e4SLinus Torvalds /* Register HCI device */
hci_register_dev(struct hci_dev * hdev)25891da177e4SLinus Torvalds int hci_register_dev(struct hci_dev *hdev)
25901da177e4SLinus Torvalds {
2591b1b813d4SDavid Herrmann int id, error;
25921da177e4SLinus Torvalds
259374292d5aSMarcel Holtmann if (!hdev->open || !hdev->close || !hdev->send)
25941da177e4SLinus Torvalds return -EINVAL;
25951da177e4SLinus Torvalds
25960a8af30aSChristophe JAILLET id = ida_alloc_max(&hci_index_ida, HCI_MAX_ID - 1, GFP_KERNEL);
25973df92b31SSasha Levin if (id < 0)
25983df92b31SSasha Levin return id;
25993df92b31SSasha Levin
2600dcda1657SLuiz Augusto von Dentz error = dev_set_name(&hdev->dev, "hci%u", id);
2601dcda1657SLuiz Augusto von Dentz if (error)
2602dcda1657SLuiz Augusto von Dentz return error;
2603dcda1657SLuiz Augusto von Dentz
2604dcda1657SLuiz Augusto von Dentz hdev->name = dev_name(&hdev->dev);
26051da177e4SLinus Torvalds hdev->id = id;
26062d8b3a11SAndrei Emeltchenko
26072d8b3a11SAndrei Emeltchenko BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
26082d8b3a11SAndrei Emeltchenko
260929e2dd0dSTejun Heo hdev->workqueue = alloc_ordered_workqueue("%s", WQ_HIGHPRI, hdev->name);
261033ca954dSDavid Herrmann if (!hdev->workqueue) {
261133ca954dSDavid Herrmann error = -ENOMEM;
261233ca954dSDavid Herrmann goto err;
261333ca954dSDavid Herrmann }
2614f48fd9c8SMarcel Holtmann
261529e2dd0dSTejun Heo hdev->req_workqueue = alloc_ordered_workqueue("%s", WQ_HIGHPRI,
261629e2dd0dSTejun Heo hdev->name);
26176ead1bbcSJohan Hedberg if (!hdev->req_workqueue) {
26186ead1bbcSJohan Hedberg destroy_workqueue(hdev->workqueue);
26196ead1bbcSJohan Hedberg error = -ENOMEM;
26206ead1bbcSJohan Hedberg goto err;
26216ead1bbcSJohan Hedberg }
26226ead1bbcSJohan Hedberg
26230153e2ecSMarcel Holtmann if (!IS_ERR_OR_NULL(bt_debugfs))
26240153e2ecSMarcel Holtmann hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs);
26250153e2ecSMarcel Holtmann
2626bdc3e0f1SMarcel Holtmann error = device_add(&hdev->dev);
262733ca954dSDavid Herrmann if (error < 0)
262854506918SJohan Hedberg goto err_wqueue;
26291da177e4SLinus Torvalds
26306d5d2ee6SHeiner Kallweit hci_leds_init(hdev);
26316d5d2ee6SHeiner Kallweit
2632611b30f7SMarcel Holtmann hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
2633a8c5fb1aSGustavo Padovan RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops,
2634a8c5fb1aSGustavo Padovan hdev);
2635611b30f7SMarcel Holtmann if (hdev->rfkill) {
2636611b30f7SMarcel Holtmann if (rfkill_register(hdev->rfkill) < 0) {
2637611b30f7SMarcel Holtmann rfkill_destroy(hdev->rfkill);
2638611b30f7SMarcel Holtmann hdev->rfkill = NULL;
2639611b30f7SMarcel Holtmann }
2640611b30f7SMarcel Holtmann }
2641611b30f7SMarcel Holtmann
26425e130367SJohan Hedberg if (hdev->rfkill && rfkill_blocked(hdev->rfkill))
2643a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_RFKILLED);
26445e130367SJohan Hedberg
2645a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_SETUP);
2646a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_AUTO_OFF);
2647ce2be9acSAndrei Emeltchenko
264856f87901SJohan Hedberg /* Assume BR/EDR support until proven otherwise (such as
264956f87901SJohan Hedberg * through reading supported features during init.
265056f87901SJohan Hedberg */
2651a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
2652ce2be9acSAndrei Emeltchenko
2653fcee3377SGustavo Padovan write_lock(&hci_dev_list_lock);
2654fcee3377SGustavo Padovan list_add(&hdev->list, &hci_dev_list);
2655fcee3377SGustavo Padovan write_unlock(&hci_dev_list_lock);
2656fcee3377SGustavo Padovan
26574a964404SMarcel Holtmann /* Devices that are marked for raw-only usage are unconfigured
26584a964404SMarcel Holtmann * and should not be included in normal operation.
2659fee746b0SMarcel Holtmann */
2660fee746b0SMarcel Holtmann if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
2661a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_UNCONFIGURED);
2662fee746b0SMarcel Holtmann
2663fe92ee64SLuiz Augusto von Dentz /* Mark Remote Wakeup connection flag as supported if driver has wakeup
2664fe92ee64SLuiz Augusto von Dentz * callback.
2665fe92ee64SLuiz Augusto von Dentz */
2666fe92ee64SLuiz Augusto von Dentz if (hdev->wakeup)
2667e1cff700SLinus Torvalds hdev->conn_flags |= HCI_CONN_FLAG_REMOTE_WAKEUP;
2668fe92ee64SLuiz Augusto von Dentz
266905fcd4c4SMarcel Holtmann hci_sock_dev_event(hdev, HCI_DEV_REG);
2670dc946bd8SDavid Herrmann hci_dev_hold(hdev);
26711da177e4SLinus Torvalds
267291117864SDan Carpenter error = hci_register_suspend_notifier(hdev);
267391117864SDan Carpenter if (error)
26740d75da38SYang Yingliang BT_WARN("register suspend notifier failed error:%d\n", error);
26759952d90eSAbhishek Pandit-Subedi
267619202573SJohan Hedberg queue_work(hdev->req_workqueue, &hdev->power_on);
2677fbe96d6fSMarcel Holtmann
2678e5e1e7fdSMiao-chen Chou idr_init(&hdev->adv_monitors_idr);
26795031ffccSMiao-chen Chou msft_register(hdev);
2680e5e1e7fdSMiao-chen Chou
26811da177e4SLinus Torvalds return id;
2682f48fd9c8SMarcel Holtmann
268333ca954dSDavid Herrmann err_wqueue:
26845a4bb6a8SWei Yongjun debugfs_remove_recursive(hdev->debugfs);
268533ca954dSDavid Herrmann destroy_workqueue(hdev->workqueue);
26866ead1bbcSJohan Hedberg destroy_workqueue(hdev->req_workqueue);
268733ca954dSDavid Herrmann err:
26880a8af30aSChristophe JAILLET ida_free(&hci_index_ida, hdev->id);
2689f48fd9c8SMarcel Holtmann
269033ca954dSDavid Herrmann return error;
26911da177e4SLinus Torvalds }
26921da177e4SLinus Torvalds EXPORT_SYMBOL(hci_register_dev);
26931da177e4SLinus Torvalds
26941da177e4SLinus Torvalds /* Unregister HCI device */
hci_unregister_dev(struct hci_dev * hdev)269559735631SDavid Herrmann void hci_unregister_dev(struct hci_dev *hdev)
26961da177e4SLinus Torvalds {
2697c13854ceSMarcel Holtmann BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
26981da177e4SLinus Torvalds
26991857c199SZhengping Jiang mutex_lock(&hdev->unregister_lock);
2700a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_UNREGISTER);
27011857c199SZhengping Jiang mutex_unlock(&hdev->unregister_lock);
270294324962SJohan Hovold
2703f20d09d5SGustavo F. Padovan write_lock(&hci_dev_list_lock);
27041da177e4SLinus Torvalds list_del(&hdev->list);
2705f20d09d5SGustavo F. Padovan write_unlock(&hci_dev_list_lock);
27061da177e4SLinus Torvalds
2707e36bea6eSVasyl Vavrychuk cancel_work_sync(&hdev->power_on);
2708e36bea6eSVasyl Vavrychuk
27096a98e383SMarcel Holtmann hci_cmd_sync_clear(hdev);
27106a98e383SMarcel Holtmann
2711359ee4f8SAbhishek Pandit-Subedi hci_unregister_suspend_notifier(hdev);
27124e8c36c3SAbhishek Pandit-Subedi
27134e8c36c3SAbhishek Pandit-Subedi hci_dev_do_close(hdev);
27149952d90eSAbhishek Pandit-Subedi
2715ab81cbf9SJohan Hedberg if (!test_bit(HCI_INIT, &hdev->flags) &&
2716d7a5a11dSMarcel Holtmann !hci_dev_test_flag(hdev, HCI_SETUP) &&
2717d7a5a11dSMarcel Holtmann !hci_dev_test_flag(hdev, HCI_CONFIG)) {
271809fd0de5SGustavo F. Padovan hci_dev_lock(hdev);
2719744cf19eSJohan Hedberg mgmt_index_removed(hdev);
272009fd0de5SGustavo F. Padovan hci_dev_unlock(hdev);
272156e5cb86SJohan Hedberg }
2722ab81cbf9SJohan Hedberg
27232e58ef3eSJohan Hedberg /* mgmt_index_removed should take care of emptying the
27242e58ef3eSJohan Hedberg * pending list */
27252e58ef3eSJohan Hedberg BUG_ON(!list_empty(&hdev->mgmt_pending));
27262e58ef3eSJohan Hedberg
272705fcd4c4SMarcel Holtmann hci_sock_dev_event(hdev, HCI_DEV_UNREG);
27281da177e4SLinus Torvalds
2729611b30f7SMarcel Holtmann if (hdev->rfkill) {
2730611b30f7SMarcel Holtmann rfkill_unregister(hdev->rfkill);
2731611b30f7SMarcel Holtmann rfkill_destroy(hdev->rfkill);
2732611b30f7SMarcel Holtmann }
2733611b30f7SMarcel Holtmann
2734bdc3e0f1SMarcel Holtmann device_del(&hdev->dev);
2735e61fbee7SDavid S. Miller /* Actual cleanup is deferred until hci_release_dev(). */
2736e0448092STetsuo Handa hci_dev_put(hdev);
2737e0448092STetsuo Handa }
2738e0448092STetsuo Handa EXPORT_SYMBOL(hci_unregister_dev);
2739147e2d59SDave Young
274058ce6d5bSTetsuo Handa /* Release HCI device */
hci_release_dev(struct hci_dev * hdev)274158ce6d5bSTetsuo Handa void hci_release_dev(struct hci_dev *hdev)
2742e0448092STetsuo Handa {
27430153e2ecSMarcel Holtmann debugfs_remove_recursive(hdev->debugfs);
27445177a838SMarcel Holtmann kfree_const(hdev->hw_info);
27455177a838SMarcel Holtmann kfree_const(hdev->fw_info);
27460153e2ecSMarcel Holtmann
2747f48fd9c8SMarcel Holtmann destroy_workqueue(hdev->workqueue);
27486ead1bbcSJohan Hedberg destroy_workqueue(hdev->req_workqueue);
2749f48fd9c8SMarcel Holtmann
275009fd0de5SGustavo F. Padovan hci_dev_lock(hdev);
27513d4f9c00SArchie Pusaka hci_bdaddr_list_clear(&hdev->reject_list);
27523d4f9c00SArchie Pusaka hci_bdaddr_list_clear(&hdev->accept_list);
27532aeb9a1aSJohan Hedberg hci_uuids_clear(hdev);
275455ed8ca1SJohan Hedberg hci_link_keys_clear(hdev);
2755b899efafSVinicius Costa Gomes hci_smp_ltks_clear(hdev);
2756970c4e46SJohan Hedberg hci_smp_irks_clear(hdev);
27572763eda6SSzymon Janc hci_remote_oob_data_clear(hdev);
2758d2609b34SFlorian Grandel hci_adv_instances_clear(hdev);
2759e5e1e7fdSMiao-chen Chou hci_adv_monitors_clear(hdev);
27603d4f9c00SArchie Pusaka hci_bdaddr_list_clear(&hdev->le_accept_list);
2761cfdb0c2dSAnkit Navik hci_bdaddr_list_clear(&hdev->le_resolv_list);
2762373110c5SJohan Hedberg hci_conn_params_clear_all(hdev);
276322078800SMarcel Holtmann hci_discovery_filter_clear(hdev);
2764600a8749SAlain Michaud hci_blocked_keys_clear(hdev);
2765b938790eSLuiz Augusto von Dentz hci_codec_list_clear(&hdev->local_codecs);
2766a85a60e6SSungwoo Kim msft_release(hdev);
276709fd0de5SGustavo F. Padovan hci_dev_unlock(hdev);
2768e2e0cacbSJohan Hedberg
276984cb0143SZiyang Xuan ida_destroy(&hdev->unset_handle_ida);
27700a8af30aSChristophe JAILLET ida_free(&hci_index_ida, hdev->id);
2771dd3b1dc3SLuiz Augusto von Dentz kfree_skb(hdev->sent_cmd);
27722af7aa66SLuiz Augusto von Dentz kfree_skb(hdev->req_skb);
2773dfe6d5c3SLuiz Augusto von Dentz kfree_skb(hdev->recv_event);
277458ce6d5bSTetsuo Handa kfree(hdev);
27751da177e4SLinus Torvalds }
277658ce6d5bSTetsuo Handa EXPORT_SYMBOL(hci_release_dev);
27771da177e4SLinus Torvalds
hci_register_suspend_notifier(struct hci_dev * hdev)2778359ee4f8SAbhishek Pandit-Subedi int hci_register_suspend_notifier(struct hci_dev *hdev)
2779359ee4f8SAbhishek Pandit-Subedi {
2780359ee4f8SAbhishek Pandit-Subedi int ret = 0;
2781359ee4f8SAbhishek Pandit-Subedi
2782b5ca3387SLuiz Augusto von Dentz if (!hdev->suspend_notifier.notifier_call &&
2783b5ca3387SLuiz Augusto von Dentz !test_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks)) {
2784359ee4f8SAbhishek Pandit-Subedi hdev->suspend_notifier.notifier_call = hci_suspend_notifier;
2785359ee4f8SAbhishek Pandit-Subedi ret = register_pm_notifier(&hdev->suspend_notifier);
2786359ee4f8SAbhishek Pandit-Subedi }
2787359ee4f8SAbhishek Pandit-Subedi
2788359ee4f8SAbhishek Pandit-Subedi return ret;
2789359ee4f8SAbhishek Pandit-Subedi }
2790359ee4f8SAbhishek Pandit-Subedi
hci_unregister_suspend_notifier(struct hci_dev * hdev)2791359ee4f8SAbhishek Pandit-Subedi int hci_unregister_suspend_notifier(struct hci_dev *hdev)
2792359ee4f8SAbhishek Pandit-Subedi {
2793359ee4f8SAbhishek Pandit-Subedi int ret = 0;
2794359ee4f8SAbhishek Pandit-Subedi
2795b5ca3387SLuiz Augusto von Dentz if (hdev->suspend_notifier.notifier_call) {
2796359ee4f8SAbhishek Pandit-Subedi ret = unregister_pm_notifier(&hdev->suspend_notifier);
2797b5ca3387SLuiz Augusto von Dentz if (!ret)
2798b5ca3387SLuiz Augusto von Dentz hdev->suspend_notifier.notifier_call = NULL;
2799b5ca3387SLuiz Augusto von Dentz }
2800359ee4f8SAbhishek Pandit-Subedi
2801359ee4f8SAbhishek Pandit-Subedi return ret;
2802359ee4f8SAbhishek Pandit-Subedi }
2803359ee4f8SAbhishek Pandit-Subedi
28040ce1229cSLuiz Augusto von Dentz /* Cancel ongoing command synchronously:
28050ce1229cSLuiz Augusto von Dentz *
28060ce1229cSLuiz Augusto von Dentz * - Cancel command timer
28070ce1229cSLuiz Augusto von Dentz * - Reset command counter
28080ce1229cSLuiz Augusto von Dentz * - Cancel command request
28090ce1229cSLuiz Augusto von Dentz */
hci_cancel_cmd_sync(struct hci_dev * hdev,int err)28100ce1229cSLuiz Augusto von Dentz static void hci_cancel_cmd_sync(struct hci_dev *hdev, int err)
28110ce1229cSLuiz Augusto von Dentz {
28120ce1229cSLuiz Augusto von Dentz bt_dev_dbg(hdev, "err 0x%2.2x", err);
28130ce1229cSLuiz Augusto von Dentz
28140ce1229cSLuiz Augusto von Dentz cancel_delayed_work_sync(&hdev->cmd_timer);
28150ce1229cSLuiz Augusto von Dentz cancel_delayed_work_sync(&hdev->ncmd_timer);
28160ce1229cSLuiz Augusto von Dentz atomic_set(&hdev->cmd_cnt, 1);
28170ce1229cSLuiz Augusto von Dentz
28189ae3954dSLuiz Augusto von Dentz hci_cmd_sync_cancel_sync(hdev, err);
28190ce1229cSLuiz Augusto von Dentz }
28200ce1229cSLuiz Augusto von Dentz
28211da177e4SLinus Torvalds /* Suspend HCI device */
hci_suspend_dev(struct hci_dev * hdev)28221da177e4SLinus Torvalds int hci_suspend_dev(struct hci_dev *hdev)
28231da177e4SLinus Torvalds {
2824e1b77d68SLuiz Augusto von Dentz int ret;
2825e1b77d68SLuiz Augusto von Dentz
2826e1b77d68SLuiz Augusto von Dentz bt_dev_dbg(hdev, "");
2827e1b77d68SLuiz Augusto von Dentz
2828e1b77d68SLuiz Augusto von Dentz /* Suspend should only act on when powered. */
2829e1b77d68SLuiz Augusto von Dentz if (!hdev_is_powered(hdev) ||
2830e1b77d68SLuiz Augusto von Dentz hci_dev_test_flag(hdev, HCI_UNREGISTER))
28311da177e4SLinus Torvalds return 0;
2832e1b77d68SLuiz Augusto von Dentz
2833182ee45dSLuiz Augusto von Dentz /* If powering down don't attempt to suspend */
2834182ee45dSLuiz Augusto von Dentz if (mgmt_powering_down(hdev))
2835182ee45dSLuiz Augusto von Dentz return 0;
2836e1b77d68SLuiz Augusto von Dentz
2837f4198635SArchie Pusaka /* Cancel potentially blocking sync operation before suspend */
28389ae3954dSLuiz Augusto von Dentz hci_cancel_cmd_sync(hdev, EHOSTDOWN);
2839f4198635SArchie Pusaka
2840182ee45dSLuiz Augusto von Dentz hci_req_sync_lock(hdev);
2841182ee45dSLuiz Augusto von Dentz ret = hci_suspend_sync(hdev);
2842182ee45dSLuiz Augusto von Dentz hci_req_sync_unlock(hdev);
28434539ca67SLuiz Augusto von Dentz
2844e1b77d68SLuiz Augusto von Dentz hci_clear_wake_reason(hdev);
2845182ee45dSLuiz Augusto von Dentz mgmt_suspending(hdev, hdev->suspend_state);
2846e1b77d68SLuiz Augusto von Dentz
2847e1b77d68SLuiz Augusto von Dentz hci_sock_dev_event(hdev, HCI_DEV_SUSPEND);
2848e1b77d68SLuiz Augusto von Dentz return ret;
28491da177e4SLinus Torvalds }
28501da177e4SLinus Torvalds EXPORT_SYMBOL(hci_suspend_dev);
28511da177e4SLinus Torvalds
28521da177e4SLinus Torvalds /* Resume HCI device */
hci_resume_dev(struct hci_dev * hdev)28531da177e4SLinus Torvalds int hci_resume_dev(struct hci_dev *hdev)
28541da177e4SLinus Torvalds {
2855e1b77d68SLuiz Augusto von Dentz int ret;
2856e1b77d68SLuiz Augusto von Dentz
2857e1b77d68SLuiz Augusto von Dentz bt_dev_dbg(hdev, "");
2858e1b77d68SLuiz Augusto von Dentz
2859e1b77d68SLuiz Augusto von Dentz /* Resume should only act on when powered. */
2860e1b77d68SLuiz Augusto von Dentz if (!hdev_is_powered(hdev) ||
2861e1b77d68SLuiz Augusto von Dentz hci_dev_test_flag(hdev, HCI_UNREGISTER))
28621da177e4SLinus Torvalds return 0;
2863e1b77d68SLuiz Augusto von Dentz
2864e1b77d68SLuiz Augusto von Dentz /* If powering down don't attempt to resume */
2865e1b77d68SLuiz Augusto von Dentz if (mgmt_powering_down(hdev))
2866e1b77d68SLuiz Augusto von Dentz return 0;
2867e1b77d68SLuiz Augusto von Dentz
2868182ee45dSLuiz Augusto von Dentz hci_req_sync_lock(hdev);
2869182ee45dSLuiz Augusto von Dentz ret = hci_resume_sync(hdev);
2870182ee45dSLuiz Augusto von Dentz hci_req_sync_unlock(hdev);
2871e1b77d68SLuiz Augusto von Dentz
2872e1b77d68SLuiz Augusto von Dentz mgmt_resuming(hdev, hdev->wake_reason, &hdev->wake_addr,
2873e1b77d68SLuiz Augusto von Dentz hdev->wake_addr_type);
2874e1b77d68SLuiz Augusto von Dentz
2875e1b77d68SLuiz Augusto von Dentz hci_sock_dev_event(hdev, HCI_DEV_RESUME);
2876e1b77d68SLuiz Augusto von Dentz return ret;
28771da177e4SLinus Torvalds }
28781da177e4SLinus Torvalds EXPORT_SYMBOL(hci_resume_dev);
28791da177e4SLinus Torvalds
288075e0569fSMarcel Holtmann /* Reset HCI device */
hci_reset_dev(struct hci_dev * hdev)288175e0569fSMarcel Holtmann int hci_reset_dev(struct hci_dev *hdev)
288275e0569fSMarcel Holtmann {
28831e4b6e91SColin Ian King static const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 };
288475e0569fSMarcel Holtmann struct sk_buff *skb;
288575e0569fSMarcel Holtmann
288675e0569fSMarcel Holtmann skb = bt_skb_alloc(3, GFP_ATOMIC);
288775e0569fSMarcel Holtmann if (!skb)
288875e0569fSMarcel Holtmann return -ENOMEM;
288975e0569fSMarcel Holtmann
2890d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
289159ae1d12SJohannes Berg skb_put_data(skb, hw_err, 3);
289275e0569fSMarcel Holtmann
2893de75cd0dSManish Mandlik bt_dev_err(hdev, "Injecting HCI hardware error event");
2894de75cd0dSManish Mandlik
289575e0569fSMarcel Holtmann /* Send Hardware Error to upper stack */
289675e0569fSMarcel Holtmann return hci_recv_frame(hdev, skb);
289775e0569fSMarcel Holtmann }
289875e0569fSMarcel Holtmann EXPORT_SYMBOL(hci_reset_dev);
289975e0569fSMarcel Holtmann
290076bca880SMarcel Holtmann /* Receive frame from HCI drivers */
hci_recv_frame(struct hci_dev * hdev,struct sk_buff * skb)2901e1a26170SMarcel Holtmann int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
290276bca880SMarcel Holtmann {
290376bca880SMarcel Holtmann if (!hdev || (!test_bit(HCI_UP, &hdev->flags)
290476bca880SMarcel Holtmann && !test_bit(HCI_INIT, &hdev->flags))) {
290576bca880SMarcel Holtmann kfree_skb(skb);
290676bca880SMarcel Holtmann return -ENXIO;
290776bca880SMarcel Holtmann }
290876bca880SMarcel Holtmann
2909876e7810SLuiz Augusto von Dentz switch (hci_skb_pkt_type(skb)) {
2910876e7810SLuiz Augusto von Dentz case HCI_EVENT_PKT:
2911876e7810SLuiz Augusto von Dentz break;
2912876e7810SLuiz Augusto von Dentz case HCI_ACLDATA_PKT:
2913876e7810SLuiz Augusto von Dentz /* Detect if ISO packet has been sent as ACL */
2914876e7810SLuiz Augusto von Dentz if (hci_conn_num(hdev, ISO_LINK)) {
2915876e7810SLuiz Augusto von Dentz __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
2916876e7810SLuiz Augusto von Dentz __u8 type;
2917876e7810SLuiz Augusto von Dentz
2918876e7810SLuiz Augusto von Dentz type = hci_conn_lookup_type(hdev, hci_handle(handle));
2919876e7810SLuiz Augusto von Dentz if (type == ISO_LINK)
2920876e7810SLuiz Augusto von Dentz hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
2921876e7810SLuiz Augusto von Dentz }
2922876e7810SLuiz Augusto von Dentz break;
2923876e7810SLuiz Augusto von Dentz case HCI_SCODATA_PKT:
2924876e7810SLuiz Augusto von Dentz break;
2925876e7810SLuiz Augusto von Dentz case HCI_ISODATA_PKT:
2926876e7810SLuiz Augusto von Dentz break;
2927876e7810SLuiz Augusto von Dentz default:
2928fe806dceSMarcel Holtmann kfree_skb(skb);
2929fe806dceSMarcel Holtmann return -EINVAL;
2930fe806dceSMarcel Holtmann }
2931fe806dceSMarcel Holtmann
2932d82603c6SJorrit Schippers /* Incoming skb */
293376bca880SMarcel Holtmann bt_cb(skb)->incoming = 1;
293476bca880SMarcel Holtmann
293576bca880SMarcel Holtmann /* Time stamp */
293676bca880SMarcel Holtmann __net_timestamp(skb);
293776bca880SMarcel Holtmann
293876bca880SMarcel Holtmann skb_queue_tail(&hdev->rx_q, skb);
2939b78752ccSMarcel Holtmann queue_work(hdev->workqueue, &hdev->rx_work);
2940c78ae283SMarcel Holtmann
294176bca880SMarcel Holtmann return 0;
294276bca880SMarcel Holtmann }
294376bca880SMarcel Holtmann EXPORT_SYMBOL(hci_recv_frame);
294476bca880SMarcel Holtmann
2945e875ff84SMarcel Holtmann /* Receive diagnostic message from HCI drivers */
hci_recv_diag(struct hci_dev * hdev,struct sk_buff * skb)2946e875ff84SMarcel Holtmann int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb)
2947e875ff84SMarcel Holtmann {
2948581d6fd6SMarcel Holtmann /* Mark as diagnostic packet */
2949d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) = HCI_DIAG_PKT;
2950581d6fd6SMarcel Holtmann
2951e875ff84SMarcel Holtmann /* Time stamp */
2952e875ff84SMarcel Holtmann __net_timestamp(skb);
2953e875ff84SMarcel Holtmann
2954581d6fd6SMarcel Holtmann skb_queue_tail(&hdev->rx_q, skb);
2955581d6fd6SMarcel Holtmann queue_work(hdev->workqueue, &hdev->rx_work);
2956e875ff84SMarcel Holtmann
2957e875ff84SMarcel Holtmann return 0;
2958e875ff84SMarcel Holtmann }
2959e875ff84SMarcel Holtmann EXPORT_SYMBOL(hci_recv_diag);
2960e875ff84SMarcel Holtmann
hci_set_hw_info(struct hci_dev * hdev,const char * fmt,...)29615177a838SMarcel Holtmann void hci_set_hw_info(struct hci_dev *hdev, const char *fmt, ...)
29625177a838SMarcel Holtmann {
29635177a838SMarcel Holtmann va_list vargs;
29645177a838SMarcel Holtmann
29655177a838SMarcel Holtmann va_start(vargs, fmt);
29665177a838SMarcel Holtmann kfree_const(hdev->hw_info);
29675177a838SMarcel Holtmann hdev->hw_info = kvasprintf_const(GFP_KERNEL, fmt, vargs);
29685177a838SMarcel Holtmann va_end(vargs);
29695177a838SMarcel Holtmann }
29705177a838SMarcel Holtmann EXPORT_SYMBOL(hci_set_hw_info);
29715177a838SMarcel Holtmann
hci_set_fw_info(struct hci_dev * hdev,const char * fmt,...)29725177a838SMarcel Holtmann void hci_set_fw_info(struct hci_dev *hdev, const char *fmt, ...)
29735177a838SMarcel Holtmann {
29745177a838SMarcel Holtmann va_list vargs;
29755177a838SMarcel Holtmann
29765177a838SMarcel Holtmann va_start(vargs, fmt);
29775177a838SMarcel Holtmann kfree_const(hdev->fw_info);
29785177a838SMarcel Holtmann hdev->fw_info = kvasprintf_const(GFP_KERNEL, fmt, vargs);
29795177a838SMarcel Holtmann va_end(vargs);
29805177a838SMarcel Holtmann }
29815177a838SMarcel Holtmann EXPORT_SYMBOL(hci_set_fw_info);
29825177a838SMarcel Holtmann
29831da177e4SLinus Torvalds /* ---- Interface to upper protocols ---- */
29841da177e4SLinus Torvalds
hci_register_cb(struct hci_cb * cb)29851da177e4SLinus Torvalds int hci_register_cb(struct hci_cb *cb)
29861da177e4SLinus Torvalds {
29871da177e4SLinus Torvalds BT_DBG("%p name %s", cb, cb->name);
29881da177e4SLinus Torvalds
2989fba7ecf0SJohan Hedberg mutex_lock(&hci_cb_list_lock);
299000629e0fSJohan Hedberg list_add_tail(&cb->list, &hci_cb_list);
2991fba7ecf0SJohan Hedberg mutex_unlock(&hci_cb_list_lock);
29921da177e4SLinus Torvalds
29931da177e4SLinus Torvalds return 0;
29941da177e4SLinus Torvalds }
29951da177e4SLinus Torvalds EXPORT_SYMBOL(hci_register_cb);
29961da177e4SLinus Torvalds
hci_unregister_cb(struct hci_cb * cb)29971da177e4SLinus Torvalds int hci_unregister_cb(struct hci_cb *cb)
29981da177e4SLinus Torvalds {
29991da177e4SLinus Torvalds BT_DBG("%p name %s", cb, cb->name);
30001da177e4SLinus Torvalds
3001fba7ecf0SJohan Hedberg mutex_lock(&hci_cb_list_lock);
30021da177e4SLinus Torvalds list_del(&cb->list);
3003fba7ecf0SJohan Hedberg mutex_unlock(&hci_cb_list_lock);
30041da177e4SLinus Torvalds
30051da177e4SLinus Torvalds return 0;
30061da177e4SLinus Torvalds }
30071da177e4SLinus Torvalds EXPORT_SYMBOL(hci_unregister_cb);
30081da177e4SLinus Torvalds
hci_send_frame(struct hci_dev * hdev,struct sk_buff * skb)30092250abadSBenjamin Berg static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
30101da177e4SLinus Torvalds {
3011cdc52faaSMarcel Holtmann int err;
3012cdc52faaSMarcel Holtmann
3013d79f34e3SMarcel Holtmann BT_DBG("%s type %d len %d", hdev->name, hci_skb_pkt_type(skb),
3014d79f34e3SMarcel Holtmann skb->len);
30151da177e4SLinus Torvalds
30161da177e4SLinus Torvalds /* Time stamp */
3017a61bbcf2SPatrick McHardy __net_timestamp(skb);
30181da177e4SLinus Torvalds
3019cd82e61cSMarcel Holtmann /* Send copy to monitor */
3020cd82e61cSMarcel Holtmann hci_send_to_monitor(hdev, skb);
3021cd82e61cSMarcel Holtmann
3022cd82e61cSMarcel Holtmann if (atomic_read(&hdev->promisc)) {
3023cd82e61cSMarcel Holtmann /* Send copy to the sockets */
3024470fe1b5SMarcel Holtmann hci_send_to_sock(hdev, skb);
30251da177e4SLinus Torvalds }
30261da177e4SLinus Torvalds
30271da177e4SLinus Torvalds /* Get rid of skb owner, prior to sending to the driver. */
30281da177e4SLinus Torvalds skb_orphan(skb);
30291da177e4SLinus Torvalds
303073d0d3c8SMarcel Holtmann if (!test_bit(HCI_RUNNING, &hdev->flags)) {
303173d0d3c8SMarcel Holtmann kfree_skb(skb);
30322250abadSBenjamin Berg return -EINVAL;
303373d0d3c8SMarcel Holtmann }
303473d0d3c8SMarcel Holtmann
3035cdc52faaSMarcel Holtmann err = hdev->send(hdev, skb);
3036cdc52faaSMarcel Holtmann if (err < 0) {
30372064ee33SMarcel Holtmann bt_dev_err(hdev, "sending frame failed (%d)", err);
3038cdc52faaSMarcel Holtmann kfree_skb(skb);
30392250abadSBenjamin Berg return err;
3040cdc52faaSMarcel Holtmann }
30412250abadSBenjamin Berg
30422250abadSBenjamin Berg return 0;
30431da177e4SLinus Torvalds }
30441da177e4SLinus Torvalds
30451ca3a9d0SJohan Hedberg /* Send HCI command */
hci_send_cmd(struct hci_dev * hdev,__u16 opcode,__u32 plen,const void * param)304607dc93ddSJohan Hedberg int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen,
304707dc93ddSJohan Hedberg const void *param)
30481ca3a9d0SJohan Hedberg {
30491ca3a9d0SJohan Hedberg struct sk_buff *skb;
30501ca3a9d0SJohan Hedberg
30511ca3a9d0SJohan Hedberg BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen);
30521ca3a9d0SJohan Hedberg
30531ca3a9d0SJohan Hedberg skb = hci_prepare_cmd(hdev, opcode, plen, param);
30541ca3a9d0SJohan Hedberg if (!skb) {
30552064ee33SMarcel Holtmann bt_dev_err(hdev, "no memory for command");
30561ca3a9d0SJohan Hedberg return -ENOMEM;
30571ca3a9d0SJohan Hedberg }
30581ca3a9d0SJohan Hedberg
305949c922bbSStephen Hemminger /* Stand-alone HCI commands must be flagged as
306011714b3dSJohan Hedberg * single-command requests.
306111714b3dSJohan Hedberg */
306244d27137SJohan Hedberg bt_cb(skb)->hci.req_flags |= HCI_REQ_START;
306311714b3dSJohan Hedberg
30641da177e4SLinus Torvalds skb_queue_tail(&hdev->cmd_q, skb);
3065c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work);
30661da177e4SLinus Torvalds
30671da177e4SLinus Torvalds return 0;
30681da177e4SLinus Torvalds }
30691da177e4SLinus Torvalds
__hci_cmd_send(struct hci_dev * hdev,u16 opcode,u32 plen,const void * param)3070d6ee6ad7SLoic Poulain int __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen,
3071d6ee6ad7SLoic Poulain const void *param)
3072d6ee6ad7SLoic Poulain {
3073d6ee6ad7SLoic Poulain struct sk_buff *skb;
3074d6ee6ad7SLoic Poulain
3075d6ee6ad7SLoic Poulain if (hci_opcode_ogf(opcode) != 0x3f) {
3076d6ee6ad7SLoic Poulain /* A controller receiving a command shall respond with either
3077d6ee6ad7SLoic Poulain * a Command Status Event or a Command Complete Event.
3078d6ee6ad7SLoic Poulain * Therefore, all standard HCI commands must be sent via the
3079d6ee6ad7SLoic Poulain * standard API, using hci_send_cmd or hci_cmd_sync helpers.
3080d6ee6ad7SLoic Poulain * Some vendors do not comply with this rule for vendor-specific
3081d6ee6ad7SLoic Poulain * commands and do not return any event. We want to support
3082d6ee6ad7SLoic Poulain * unresponded commands for such cases only.
3083d6ee6ad7SLoic Poulain */
3084d6ee6ad7SLoic Poulain bt_dev_err(hdev, "unresponded command not supported");
3085d6ee6ad7SLoic Poulain return -EINVAL;
3086d6ee6ad7SLoic Poulain }
3087d6ee6ad7SLoic Poulain
3088d6ee6ad7SLoic Poulain skb = hci_prepare_cmd(hdev, opcode, plen, param);
3089d6ee6ad7SLoic Poulain if (!skb) {
3090d6ee6ad7SLoic Poulain bt_dev_err(hdev, "no memory for command (opcode 0x%4.4x)",
3091d6ee6ad7SLoic Poulain opcode);
3092d6ee6ad7SLoic Poulain return -ENOMEM;
3093d6ee6ad7SLoic Poulain }
3094d6ee6ad7SLoic Poulain
3095d6ee6ad7SLoic Poulain hci_send_frame(hdev, skb);
3096d6ee6ad7SLoic Poulain
3097d6ee6ad7SLoic Poulain return 0;
3098d6ee6ad7SLoic Poulain }
3099d6ee6ad7SLoic Poulain EXPORT_SYMBOL(__hci_cmd_send);
3100d6ee6ad7SLoic Poulain
31011da177e4SLinus Torvalds /* Get data from the previously sent command */
hci_cmd_data(struct sk_buff * skb,__u16 opcode)31022af7aa66SLuiz Augusto von Dentz static void *hci_cmd_data(struct sk_buff *skb, __u16 opcode)
31031da177e4SLinus Torvalds {
31041da177e4SLinus Torvalds struct hci_command_hdr *hdr;
31051da177e4SLinus Torvalds
31062af7aa66SLuiz Augusto von Dentz if (!skb || skb->len < HCI_COMMAND_HDR_SIZE)
31071da177e4SLinus Torvalds return NULL;
31081da177e4SLinus Torvalds
31092af7aa66SLuiz Augusto von Dentz hdr = (void *)skb->data;
31101da177e4SLinus Torvalds
3111a9de9248SMarcel Holtmann if (hdr->opcode != cpu_to_le16(opcode))
31121da177e4SLinus Torvalds return NULL;
31131da177e4SLinus Torvalds
31142af7aa66SLuiz Augusto von Dentz return skb->data + HCI_COMMAND_HDR_SIZE;
31152af7aa66SLuiz Augusto von Dentz }
31161da177e4SLinus Torvalds
31172af7aa66SLuiz Augusto von Dentz /* Get data from the previously sent command */
hci_sent_cmd_data(struct hci_dev * hdev,__u16 opcode)31182af7aa66SLuiz Augusto von Dentz void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
31192af7aa66SLuiz Augusto von Dentz {
31202af7aa66SLuiz Augusto von Dentz void *data;
31212af7aa66SLuiz Augusto von Dentz
31222af7aa66SLuiz Augusto von Dentz /* Check if opcode matches last sent command */
31232af7aa66SLuiz Augusto von Dentz data = hci_cmd_data(hdev->sent_cmd, opcode);
31242af7aa66SLuiz Augusto von Dentz if (!data)
31252af7aa66SLuiz Augusto von Dentz /* Check if opcode matches last request */
31262af7aa66SLuiz Augusto von Dentz data = hci_cmd_data(hdev->req_skb, opcode);
31272af7aa66SLuiz Augusto von Dentz
31282af7aa66SLuiz Augusto von Dentz return data;
31291da177e4SLinus Torvalds }
31301da177e4SLinus Torvalds
3131dfe6d5c3SLuiz Augusto von Dentz /* Get data from last received event */
hci_recv_event_data(struct hci_dev * hdev,__u8 event)3132dfe6d5c3SLuiz Augusto von Dentz void *hci_recv_event_data(struct hci_dev *hdev, __u8 event)
3133dfe6d5c3SLuiz Augusto von Dentz {
3134dfe6d5c3SLuiz Augusto von Dentz struct hci_event_hdr *hdr;
3135dfe6d5c3SLuiz Augusto von Dentz int offset;
3136dfe6d5c3SLuiz Augusto von Dentz
3137dfe6d5c3SLuiz Augusto von Dentz if (!hdev->recv_event)
3138dfe6d5c3SLuiz Augusto von Dentz return NULL;
3139dfe6d5c3SLuiz Augusto von Dentz
3140dfe6d5c3SLuiz Augusto von Dentz hdr = (void *)hdev->recv_event->data;
3141dfe6d5c3SLuiz Augusto von Dentz offset = sizeof(*hdr);
3142dfe6d5c3SLuiz Augusto von Dentz
3143dfe6d5c3SLuiz Augusto von Dentz if (hdr->evt != event) {
3144dfe6d5c3SLuiz Augusto von Dentz /* In case of LE metaevent check the subevent match */
3145dfe6d5c3SLuiz Augusto von Dentz if (hdr->evt == HCI_EV_LE_META) {
3146dfe6d5c3SLuiz Augusto von Dentz struct hci_ev_le_meta *ev;
3147dfe6d5c3SLuiz Augusto von Dentz
3148dfe6d5c3SLuiz Augusto von Dentz ev = (void *)hdev->recv_event->data + offset;
3149dfe6d5c3SLuiz Augusto von Dentz offset += sizeof(*ev);
3150dfe6d5c3SLuiz Augusto von Dentz if (ev->subevent == event)
3151dfe6d5c3SLuiz Augusto von Dentz goto found;
3152dfe6d5c3SLuiz Augusto von Dentz }
3153dfe6d5c3SLuiz Augusto von Dentz return NULL;
3154dfe6d5c3SLuiz Augusto von Dentz }
3155dfe6d5c3SLuiz Augusto von Dentz
3156dfe6d5c3SLuiz Augusto von Dentz found:
3157dfe6d5c3SLuiz Augusto von Dentz bt_dev_dbg(hdev, "event 0x%2.2x", event);
3158dfe6d5c3SLuiz Augusto von Dentz
3159dfe6d5c3SLuiz Augusto von Dentz return hdev->recv_event->data + offset;
3160dfe6d5c3SLuiz Augusto von Dentz }
3161dfe6d5c3SLuiz Augusto von Dentz
31621da177e4SLinus Torvalds /* Send ACL data */
hci_add_acl_hdr(struct sk_buff * skb,__u16 handle,__u16 flags)31631da177e4SLinus Torvalds static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
31641da177e4SLinus Torvalds {
31651da177e4SLinus Torvalds struct hci_acl_hdr *hdr;
31661da177e4SLinus Torvalds int len = skb->len;
31671da177e4SLinus Torvalds
3168badff6d0SArnaldo Carvalho de Melo skb_push(skb, HCI_ACL_HDR_SIZE);
3169badff6d0SArnaldo Carvalho de Melo skb_reset_transport_header(skb);
31709c70220bSArnaldo Carvalho de Melo hdr = (struct hci_acl_hdr *)skb_transport_header(skb);
3171aca3192cSYOSHIFUJI Hideaki hdr->handle = cpu_to_le16(hci_handle_pack(handle, flags));
3172aca3192cSYOSHIFUJI Hideaki hdr->dlen = cpu_to_le16(len);
31731da177e4SLinus Torvalds }
31741da177e4SLinus Torvalds
hci_queue_acl(struct hci_chan * chan,struct sk_buff_head * queue,struct sk_buff * skb,__u16 flags)3175ee22be7eSAndrei Emeltchenko static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,
317673d80debSLuiz Augusto von Dentz struct sk_buff *skb, __u16 flags)
31771da177e4SLinus Torvalds {
3178ee22be7eSAndrei Emeltchenko struct hci_conn *conn = chan->conn;
31791da177e4SLinus Torvalds struct hci_dev *hdev = conn->hdev;
31801da177e4SLinus Torvalds struct sk_buff *list;
31811da177e4SLinus Torvalds
3182087bfd99SGustavo Padovan skb->len = skb_headlen(skb);
3183087bfd99SGustavo Padovan skb->data_len = 0;
3184087bfd99SGustavo Padovan
3185d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
3186204a6e54SAndrei Emeltchenko
3187087bfd99SGustavo Padovan hci_add_acl_hdr(skb, conn->handle, flags);
3188087bfd99SGustavo Padovan
318970f23020SAndrei Emeltchenko list = skb_shinfo(skb)->frag_list;
319070f23020SAndrei Emeltchenko if (!list) {
31911da177e4SLinus Torvalds /* Non fragmented */
31921da177e4SLinus Torvalds BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len);
31931da177e4SLinus Torvalds
319473d80debSLuiz Augusto von Dentz skb_queue_tail(queue, skb);
31951da177e4SLinus Torvalds } else {
31961da177e4SLinus Torvalds /* Fragmented */
31971da177e4SLinus Torvalds BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
31981da177e4SLinus Torvalds
31991da177e4SLinus Torvalds skb_shinfo(skb)->frag_list = NULL;
32001da177e4SLinus Torvalds
32019cfd5a23SJukka Rissanen /* Queue all fragments atomically. We need to use spin_lock_bh
32029cfd5a23SJukka Rissanen * here because of 6LoWPAN links, as there this function is
32039cfd5a23SJukka Rissanen * called from softirq and using normal spin lock could cause
32049cfd5a23SJukka Rissanen * deadlocks.
32059cfd5a23SJukka Rissanen */
32069cfd5a23SJukka Rissanen spin_lock_bh(&queue->lock);
32071da177e4SLinus Torvalds
320873d80debSLuiz Augusto von Dentz __skb_queue_tail(queue, skb);
3209e702112fSAndrei Emeltchenko
3210e702112fSAndrei Emeltchenko flags &= ~ACL_START;
3211e702112fSAndrei Emeltchenko flags |= ACL_CONT;
32121da177e4SLinus Torvalds do {
32131da177e4SLinus Torvalds skb = list; list = list->next;
32141da177e4SLinus Torvalds
3215d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
3216e702112fSAndrei Emeltchenko hci_add_acl_hdr(skb, conn->handle, flags);
32171da177e4SLinus Torvalds
32181da177e4SLinus Torvalds BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
32191da177e4SLinus Torvalds
322073d80debSLuiz Augusto von Dentz __skb_queue_tail(queue, skb);
32211da177e4SLinus Torvalds } while (list);
32221da177e4SLinus Torvalds
32239cfd5a23SJukka Rissanen spin_unlock_bh(&queue->lock);
32241da177e4SLinus Torvalds }
322573d80debSLuiz Augusto von Dentz }
322673d80debSLuiz Augusto von Dentz
hci_send_acl(struct hci_chan * chan,struct sk_buff * skb,__u16 flags)322773d80debSLuiz Augusto von Dentz void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
322873d80debSLuiz Augusto von Dentz {
3229ee22be7eSAndrei Emeltchenko struct hci_dev *hdev = chan->conn->hdev;
323073d80debSLuiz Augusto von Dentz
3231f0e09510SAndrei Emeltchenko BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags);
323273d80debSLuiz Augusto von Dentz
3233ee22be7eSAndrei Emeltchenko hci_queue_acl(chan, &chan->data_q, skb, flags);
32341da177e4SLinus Torvalds
32353eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work);
32361da177e4SLinus Torvalds }
32371da177e4SLinus Torvalds
32381da177e4SLinus Torvalds /* Send SCO data */
hci_send_sco(struct hci_conn * conn,struct sk_buff * skb)32390d861d8bSGustavo F. Padovan void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
32401da177e4SLinus Torvalds {
32411da177e4SLinus Torvalds struct hci_dev *hdev = conn->hdev;
32421da177e4SLinus Torvalds struct hci_sco_hdr hdr;
32431da177e4SLinus Torvalds
32441da177e4SLinus Torvalds BT_DBG("%s len %d", hdev->name, skb->len);
32451da177e4SLinus Torvalds
3246aca3192cSYOSHIFUJI Hideaki hdr.handle = cpu_to_le16(conn->handle);
32471da177e4SLinus Torvalds hdr.dlen = skb->len;
32481da177e4SLinus Torvalds
3249badff6d0SArnaldo Carvalho de Melo skb_push(skb, HCI_SCO_HDR_SIZE);
3250badff6d0SArnaldo Carvalho de Melo skb_reset_transport_header(skb);
32519c70220bSArnaldo Carvalho de Melo memcpy(skb_transport_header(skb), &hdr, HCI_SCO_HDR_SIZE);
32521da177e4SLinus Torvalds
3253d79f34e3SMarcel Holtmann hci_skb_pkt_type(skb) = HCI_SCODATA_PKT;
3254c78ae283SMarcel Holtmann
32551da177e4SLinus Torvalds skb_queue_tail(&conn->data_q, skb);
32563eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work);
32571da177e4SLinus Torvalds }
32581da177e4SLinus Torvalds
325926afbd82SLuiz Augusto von Dentz /* Send ISO data */
hci_add_iso_hdr(struct sk_buff * skb,__u16 handle,__u8 flags)326026afbd82SLuiz Augusto von Dentz static void hci_add_iso_hdr(struct sk_buff *skb, __u16 handle, __u8 flags)
326126afbd82SLuiz Augusto von Dentz {
326226afbd82SLuiz Augusto von Dentz struct hci_iso_hdr *hdr;
326326afbd82SLuiz Augusto von Dentz int len = skb->len;
326426afbd82SLuiz Augusto von Dentz
326526afbd82SLuiz Augusto von Dentz skb_push(skb, HCI_ISO_HDR_SIZE);
326626afbd82SLuiz Augusto von Dentz skb_reset_transport_header(skb);
326726afbd82SLuiz Augusto von Dentz hdr = (struct hci_iso_hdr *)skb_transport_header(skb);
326826afbd82SLuiz Augusto von Dentz hdr->handle = cpu_to_le16(hci_handle_pack(handle, flags));
326926afbd82SLuiz Augusto von Dentz hdr->dlen = cpu_to_le16(len);
327026afbd82SLuiz Augusto von Dentz }
327126afbd82SLuiz Augusto von Dentz
hci_queue_iso(struct hci_conn * conn,struct sk_buff_head * queue,struct sk_buff * skb)327226afbd82SLuiz Augusto von Dentz static void hci_queue_iso(struct hci_conn *conn, struct sk_buff_head *queue,
327326afbd82SLuiz Augusto von Dentz struct sk_buff *skb)
327426afbd82SLuiz Augusto von Dentz {
327526afbd82SLuiz Augusto von Dentz struct hci_dev *hdev = conn->hdev;
327626afbd82SLuiz Augusto von Dentz struct sk_buff *list;
327726afbd82SLuiz Augusto von Dentz __u16 flags;
327826afbd82SLuiz Augusto von Dentz
327926afbd82SLuiz Augusto von Dentz skb->len = skb_headlen(skb);
328026afbd82SLuiz Augusto von Dentz skb->data_len = 0;
328126afbd82SLuiz Augusto von Dentz
328226afbd82SLuiz Augusto von Dentz hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
328326afbd82SLuiz Augusto von Dentz
328426afbd82SLuiz Augusto von Dentz list = skb_shinfo(skb)->frag_list;
328526afbd82SLuiz Augusto von Dentz
328626afbd82SLuiz Augusto von Dentz flags = hci_iso_flags_pack(list ? ISO_START : ISO_SINGLE, 0x00);
328726afbd82SLuiz Augusto von Dentz hci_add_iso_hdr(skb, conn->handle, flags);
328826afbd82SLuiz Augusto von Dentz
328926afbd82SLuiz Augusto von Dentz if (!list) {
329026afbd82SLuiz Augusto von Dentz /* Non fragmented */
329126afbd82SLuiz Augusto von Dentz BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len);
329226afbd82SLuiz Augusto von Dentz
329326afbd82SLuiz Augusto von Dentz skb_queue_tail(queue, skb);
329426afbd82SLuiz Augusto von Dentz } else {
329526afbd82SLuiz Augusto von Dentz /* Fragmented */
329626afbd82SLuiz Augusto von Dentz BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
329726afbd82SLuiz Augusto von Dentz
329826afbd82SLuiz Augusto von Dentz skb_shinfo(skb)->frag_list = NULL;
329926afbd82SLuiz Augusto von Dentz
330026afbd82SLuiz Augusto von Dentz __skb_queue_tail(queue, skb);
330126afbd82SLuiz Augusto von Dentz
330226afbd82SLuiz Augusto von Dentz do {
330326afbd82SLuiz Augusto von Dentz skb = list; list = list->next;
330426afbd82SLuiz Augusto von Dentz
330526afbd82SLuiz Augusto von Dentz hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
330626afbd82SLuiz Augusto von Dentz flags = hci_iso_flags_pack(list ? ISO_CONT : ISO_END,
330726afbd82SLuiz Augusto von Dentz 0x00);
330826afbd82SLuiz Augusto von Dentz hci_add_iso_hdr(skb, conn->handle, flags);
330926afbd82SLuiz Augusto von Dentz
331026afbd82SLuiz Augusto von Dentz BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
331126afbd82SLuiz Augusto von Dentz
331226afbd82SLuiz Augusto von Dentz __skb_queue_tail(queue, skb);
331326afbd82SLuiz Augusto von Dentz } while (list);
331426afbd82SLuiz Augusto von Dentz }
331526afbd82SLuiz Augusto von Dentz }
331626afbd82SLuiz Augusto von Dentz
hci_send_iso(struct hci_conn * conn,struct sk_buff * skb)331726afbd82SLuiz Augusto von Dentz void hci_send_iso(struct hci_conn *conn, struct sk_buff *skb)
331826afbd82SLuiz Augusto von Dentz {
331926afbd82SLuiz Augusto von Dentz struct hci_dev *hdev = conn->hdev;
332026afbd82SLuiz Augusto von Dentz
332126afbd82SLuiz Augusto von Dentz BT_DBG("%s len %d", hdev->name, skb->len);
332226afbd82SLuiz Augusto von Dentz
332326afbd82SLuiz Augusto von Dentz hci_queue_iso(conn, &conn->data_q, skb);
332426afbd82SLuiz Augusto von Dentz
332526afbd82SLuiz Augusto von Dentz queue_work(hdev->workqueue, &hdev->tx_work);
332626afbd82SLuiz Augusto von Dentz }
332726afbd82SLuiz Augusto von Dentz
33281da177e4SLinus Torvalds /* ---- HCI TX task (outgoing data) ---- */
33291da177e4SLinus Torvalds
33301da177e4SLinus Torvalds /* HCI Connection scheduler */
hci_quote_sent(struct hci_conn * conn,int num,int * quote)333126afbd82SLuiz Augusto von Dentz static inline void hci_quote_sent(struct hci_conn *conn, int num, int *quote)
333226afbd82SLuiz Augusto von Dentz {
333326afbd82SLuiz Augusto von Dentz struct hci_dev *hdev;
333426afbd82SLuiz Augusto von Dentz int cnt, q;
333526afbd82SLuiz Augusto von Dentz
333626afbd82SLuiz Augusto von Dentz if (!conn) {
333726afbd82SLuiz Augusto von Dentz *quote = 0;
333826afbd82SLuiz Augusto von Dentz return;
333926afbd82SLuiz Augusto von Dentz }
334026afbd82SLuiz Augusto von Dentz
334126afbd82SLuiz Augusto von Dentz hdev = conn->hdev;
334226afbd82SLuiz Augusto von Dentz
334326afbd82SLuiz Augusto von Dentz switch (conn->type) {
334426afbd82SLuiz Augusto von Dentz case ACL_LINK:
334526afbd82SLuiz Augusto von Dentz cnt = hdev->acl_cnt;
334626afbd82SLuiz Augusto von Dentz break;
334726afbd82SLuiz Augusto von Dentz case SCO_LINK:
334826afbd82SLuiz Augusto von Dentz case ESCO_LINK:
334926afbd82SLuiz Augusto von Dentz cnt = hdev->sco_cnt;
335026afbd82SLuiz Augusto von Dentz break;
335126afbd82SLuiz Augusto von Dentz case LE_LINK:
335226afbd82SLuiz Augusto von Dentz cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
335326afbd82SLuiz Augusto von Dentz break;
335426afbd82SLuiz Augusto von Dentz case ISO_LINK:
335526afbd82SLuiz Augusto von Dentz cnt = hdev->iso_mtu ? hdev->iso_cnt :
335626afbd82SLuiz Augusto von Dentz hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
335726afbd82SLuiz Augusto von Dentz break;
335826afbd82SLuiz Augusto von Dentz default:
335926afbd82SLuiz Augusto von Dentz cnt = 0;
336026afbd82SLuiz Augusto von Dentz bt_dev_err(hdev, "unknown link type %d", conn->type);
336126afbd82SLuiz Augusto von Dentz }
336226afbd82SLuiz Augusto von Dentz
336326afbd82SLuiz Augusto von Dentz q = cnt / num;
336426afbd82SLuiz Augusto von Dentz *quote = q ? q : 1;
336526afbd82SLuiz Augusto von Dentz }
336626afbd82SLuiz Augusto von Dentz
hci_low_sent(struct hci_dev * hdev,__u8 type,int * quote)33676039aa73SGustavo Padovan static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type,
3368a8c5fb1aSGustavo Padovan int *quote)
33691da177e4SLinus Torvalds {
33701da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash;
33718035ded4SLuiz Augusto von Dentz struct hci_conn *conn = NULL, *c;
3372abc5de8fSMikel Astiz unsigned int num = 0, min = ~0;
33731da177e4SLinus Torvalds
33741da177e4SLinus Torvalds /* We don't have to lock device here. Connections are always
33751da177e4SLinus Torvalds * added and removed with TX task disabled. */
3376bf4c6325SGustavo F. Padovan
3377bf4c6325SGustavo F. Padovan rcu_read_lock();
3378bf4c6325SGustavo F. Padovan
3379bf4c6325SGustavo F. Padovan list_for_each_entry_rcu(c, &h->list, list) {
3380769be974SMarcel Holtmann if (c->type != type || skb_queue_empty(&c->data_q))
33811da177e4SLinus Torvalds continue;
3382769be974SMarcel Holtmann
3383769be974SMarcel Holtmann if (c->state != BT_CONNECTED && c->state != BT_CONFIG)
3384769be974SMarcel Holtmann continue;
3385769be974SMarcel Holtmann
33861da177e4SLinus Torvalds num++;
33871da177e4SLinus Torvalds
33881da177e4SLinus Torvalds if (c->sent < min) {
33891da177e4SLinus Torvalds min = c->sent;
33901da177e4SLinus Torvalds conn = c;
33911da177e4SLinus Torvalds }
339252087a79SLuiz Augusto von Dentz
339352087a79SLuiz Augusto von Dentz if (hci_conn_num(hdev, type) == num)
339452087a79SLuiz Augusto von Dentz break;
33951da177e4SLinus Torvalds }
33961da177e4SLinus Torvalds
3397bf4c6325SGustavo F. Padovan rcu_read_unlock();
3398bf4c6325SGustavo F. Padovan
339926afbd82SLuiz Augusto von Dentz hci_quote_sent(conn, num, quote);
34001da177e4SLinus Torvalds
34011da177e4SLinus Torvalds BT_DBG("conn %p quote %d", conn, *quote);
34021da177e4SLinus Torvalds return conn;
34031da177e4SLinus Torvalds }
34041da177e4SLinus Torvalds
hci_link_tx_to(struct hci_dev * hdev,__u8 type)34056039aa73SGustavo Padovan static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
34061da177e4SLinus Torvalds {
34071da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash;
34081da177e4SLinus Torvalds struct hci_conn *c;
34091da177e4SLinus Torvalds
34102064ee33SMarcel Holtmann bt_dev_err(hdev, "link tx timeout");
34111da177e4SLinus Torvalds
3412bf4c6325SGustavo F. Padovan rcu_read_lock();
3413bf4c6325SGustavo F. Padovan
34141da177e4SLinus Torvalds /* Kill stalled connections */
3415bf4c6325SGustavo F. Padovan list_for_each_entry_rcu(c, &h->list, list) {
3416bae1f5d9SVille Tervo if (c->type == type && c->sent) {
34172064ee33SMarcel Holtmann bt_dev_err(hdev, "killing stalled connection %pMR",
34182064ee33SMarcel Holtmann &c->dst);
3419c7eaf80bSYing Hsu /* hci_disconnect might sleep, so, we have to release
3420c7eaf80bSYing Hsu * the RCU read lock before calling it.
3421c7eaf80bSYing Hsu */
3422c7eaf80bSYing Hsu rcu_read_unlock();
3423bed71748SAndre Guedes hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM);
3424c7eaf80bSYing Hsu rcu_read_lock();
34251da177e4SLinus Torvalds }
34261da177e4SLinus Torvalds }
3427bf4c6325SGustavo F. Padovan
3428bf4c6325SGustavo F. Padovan rcu_read_unlock();
34291da177e4SLinus Torvalds }
34301da177e4SLinus Torvalds
hci_chan_sent(struct hci_dev * hdev,__u8 type,int * quote)34316039aa73SGustavo Padovan static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
343273d80debSLuiz Augusto von Dentz int *quote)
343373d80debSLuiz Augusto von Dentz {
343473d80debSLuiz Augusto von Dentz struct hci_conn_hash *h = &hdev->conn_hash;
343573d80debSLuiz Augusto von Dentz struct hci_chan *chan = NULL;
3436abc5de8fSMikel Astiz unsigned int num = 0, min = ~0, cur_prio = 0;
343773d80debSLuiz Augusto von Dentz struct hci_conn *conn;
343826afbd82SLuiz Augusto von Dentz int conn_num = 0;
343973d80debSLuiz Augusto von Dentz
344073d80debSLuiz Augusto von Dentz BT_DBG("%s", hdev->name);
344173d80debSLuiz Augusto von Dentz
3442bf4c6325SGustavo F. Padovan rcu_read_lock();
3443bf4c6325SGustavo F. Padovan
3444bf4c6325SGustavo F. Padovan list_for_each_entry_rcu(conn, &h->list, list) {
344573d80debSLuiz Augusto von Dentz struct hci_chan *tmp;
344673d80debSLuiz Augusto von Dentz
344773d80debSLuiz Augusto von Dentz if (conn->type != type)
344873d80debSLuiz Augusto von Dentz continue;
344973d80debSLuiz Augusto von Dentz
345073d80debSLuiz Augusto von Dentz if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
345173d80debSLuiz Augusto von Dentz continue;
345273d80debSLuiz Augusto von Dentz
345373d80debSLuiz Augusto von Dentz conn_num++;
345473d80debSLuiz Augusto von Dentz
34558192edefSGustavo F. Padovan list_for_each_entry_rcu(tmp, &conn->chan_list, list) {
345673d80debSLuiz Augusto von Dentz struct sk_buff *skb;
345773d80debSLuiz Augusto von Dentz
345873d80debSLuiz Augusto von Dentz if (skb_queue_empty(&tmp->data_q))
345973d80debSLuiz Augusto von Dentz continue;
346073d80debSLuiz Augusto von Dentz
346173d80debSLuiz Augusto von Dentz skb = skb_peek(&tmp->data_q);
346273d80debSLuiz Augusto von Dentz if (skb->priority < cur_prio)
346373d80debSLuiz Augusto von Dentz continue;
346473d80debSLuiz Augusto von Dentz
346573d80debSLuiz Augusto von Dentz if (skb->priority > cur_prio) {
346673d80debSLuiz Augusto von Dentz num = 0;
346773d80debSLuiz Augusto von Dentz min = ~0;
346873d80debSLuiz Augusto von Dentz cur_prio = skb->priority;
346973d80debSLuiz Augusto von Dentz }
347073d80debSLuiz Augusto von Dentz
347173d80debSLuiz Augusto von Dentz num++;
347273d80debSLuiz Augusto von Dentz
347373d80debSLuiz Augusto von Dentz if (conn->sent < min) {
347473d80debSLuiz Augusto von Dentz min = conn->sent;
347573d80debSLuiz Augusto von Dentz chan = tmp;
347673d80debSLuiz Augusto von Dentz }
347773d80debSLuiz Augusto von Dentz }
347873d80debSLuiz Augusto von Dentz
347973d80debSLuiz Augusto von Dentz if (hci_conn_num(hdev, type) == conn_num)
348073d80debSLuiz Augusto von Dentz break;
348173d80debSLuiz Augusto von Dentz }
348273d80debSLuiz Augusto von Dentz
3483bf4c6325SGustavo F. Padovan rcu_read_unlock();
3484bf4c6325SGustavo F. Padovan
348573d80debSLuiz Augusto von Dentz if (!chan)
348673d80debSLuiz Augusto von Dentz return NULL;
348773d80debSLuiz Augusto von Dentz
348826afbd82SLuiz Augusto von Dentz hci_quote_sent(chan->conn, num, quote);
348973d80debSLuiz Augusto von Dentz
349073d80debSLuiz Augusto von Dentz BT_DBG("chan %p quote %d", chan, *quote);
349173d80debSLuiz Augusto von Dentz return chan;
349273d80debSLuiz Augusto von Dentz }
349373d80debSLuiz Augusto von Dentz
hci_prio_recalculate(struct hci_dev * hdev,__u8 type)349402b20f0bSLuiz Augusto von Dentz static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
349502b20f0bSLuiz Augusto von Dentz {
349602b20f0bSLuiz Augusto von Dentz struct hci_conn_hash *h = &hdev->conn_hash;
349702b20f0bSLuiz Augusto von Dentz struct hci_conn *conn;
349802b20f0bSLuiz Augusto von Dentz int num = 0;
349902b20f0bSLuiz Augusto von Dentz
350002b20f0bSLuiz Augusto von Dentz BT_DBG("%s", hdev->name);
350102b20f0bSLuiz Augusto von Dentz
3502bf4c6325SGustavo F. Padovan rcu_read_lock();
3503bf4c6325SGustavo F. Padovan
3504bf4c6325SGustavo F. Padovan list_for_each_entry_rcu(conn, &h->list, list) {
350502b20f0bSLuiz Augusto von Dentz struct hci_chan *chan;
350602b20f0bSLuiz Augusto von Dentz
350702b20f0bSLuiz Augusto von Dentz if (conn->type != type)
350802b20f0bSLuiz Augusto von Dentz continue;
350902b20f0bSLuiz Augusto von Dentz
351002b20f0bSLuiz Augusto von Dentz if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
351102b20f0bSLuiz Augusto von Dentz continue;
351202b20f0bSLuiz Augusto von Dentz
351302b20f0bSLuiz Augusto von Dentz num++;
351402b20f0bSLuiz Augusto von Dentz
35158192edefSGustavo F. Padovan list_for_each_entry_rcu(chan, &conn->chan_list, list) {
351602b20f0bSLuiz Augusto von Dentz struct sk_buff *skb;
351702b20f0bSLuiz Augusto von Dentz
351802b20f0bSLuiz Augusto von Dentz if (chan->sent) {
351902b20f0bSLuiz Augusto von Dentz chan->sent = 0;
352002b20f0bSLuiz Augusto von Dentz continue;
352102b20f0bSLuiz Augusto von Dentz }
352202b20f0bSLuiz Augusto von Dentz
352302b20f0bSLuiz Augusto von Dentz if (skb_queue_empty(&chan->data_q))
352402b20f0bSLuiz Augusto von Dentz continue;
352502b20f0bSLuiz Augusto von Dentz
352602b20f0bSLuiz Augusto von Dentz skb = skb_peek(&chan->data_q);
352702b20f0bSLuiz Augusto von Dentz if (skb->priority >= HCI_PRIO_MAX - 1)
352802b20f0bSLuiz Augusto von Dentz continue;
352902b20f0bSLuiz Augusto von Dentz
353002b20f0bSLuiz Augusto von Dentz skb->priority = HCI_PRIO_MAX - 1;
353102b20f0bSLuiz Augusto von Dentz
353202b20f0bSLuiz Augusto von Dentz BT_DBG("chan %p skb %p promoted to %d", chan, skb,
353302b20f0bSLuiz Augusto von Dentz skb->priority);
353402b20f0bSLuiz Augusto von Dentz }
353502b20f0bSLuiz Augusto von Dentz
353602b20f0bSLuiz Augusto von Dentz if (hci_conn_num(hdev, type) == num)
353702b20f0bSLuiz Augusto von Dentz break;
353802b20f0bSLuiz Augusto von Dentz }
3539bf4c6325SGustavo F. Padovan
3540bf4c6325SGustavo F. Padovan rcu_read_unlock();
3541bf4c6325SGustavo F. Padovan
354202b20f0bSLuiz Augusto von Dentz }
354302b20f0bSLuiz Augusto von Dentz
__check_timeout(struct hci_dev * hdev,unsigned int cnt,u8 type)3544116523c8SLuiz Augusto von Dentz static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type)
35451da177e4SLinus Torvalds {
3546116523c8SLuiz Augusto von Dentz unsigned long last_tx;
3547116523c8SLuiz Augusto von Dentz
3548116523c8SLuiz Augusto von Dentz if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
3549116523c8SLuiz Augusto von Dentz return;
3550116523c8SLuiz Augusto von Dentz
3551116523c8SLuiz Augusto von Dentz switch (type) {
3552116523c8SLuiz Augusto von Dentz case LE_LINK:
3553116523c8SLuiz Augusto von Dentz last_tx = hdev->le_last_tx;
3554116523c8SLuiz Augusto von Dentz break;
3555116523c8SLuiz Augusto von Dentz default:
3556116523c8SLuiz Augusto von Dentz last_tx = hdev->acl_last_tx;
3557116523c8SLuiz Augusto von Dentz break;
35581da177e4SLinus Torvalds }
3559116523c8SLuiz Augusto von Dentz
3560116523c8SLuiz Augusto von Dentz /* tx timeout must be longer than maximum link supervision timeout
3561116523c8SLuiz Augusto von Dentz * (40.9 seconds)
3562116523c8SLuiz Augusto von Dentz */
3563116523c8SLuiz Augusto von Dentz if (!cnt && time_after(jiffies, last_tx + HCI_ACL_TX_TIMEOUT))
3564116523c8SLuiz Augusto von Dentz hci_link_tx_to(hdev, type);
356563d2bc1bSAndrei Emeltchenko }
35661da177e4SLinus Torvalds
35677fedd3bbSAbhishek Pandit-Subedi /* Schedule SCO */
hci_sched_sco(struct hci_dev * hdev)35687fedd3bbSAbhishek Pandit-Subedi static void hci_sched_sco(struct hci_dev *hdev)
35697fedd3bbSAbhishek Pandit-Subedi {
35707fedd3bbSAbhishek Pandit-Subedi struct hci_conn *conn;
35717fedd3bbSAbhishek Pandit-Subedi struct sk_buff *skb;
35727fedd3bbSAbhishek Pandit-Subedi int quote;
35737fedd3bbSAbhishek Pandit-Subedi
35747fedd3bbSAbhishek Pandit-Subedi BT_DBG("%s", hdev->name);
35757fedd3bbSAbhishek Pandit-Subedi
35767fedd3bbSAbhishek Pandit-Subedi if (!hci_conn_num(hdev, SCO_LINK))
35777fedd3bbSAbhishek Pandit-Subedi return;
35787fedd3bbSAbhishek Pandit-Subedi
35797fedd3bbSAbhishek Pandit-Subedi while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, "e))) {
35807fedd3bbSAbhishek Pandit-Subedi while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
35817fedd3bbSAbhishek Pandit-Subedi BT_DBG("skb %p len %d", skb, skb->len);
35827fedd3bbSAbhishek Pandit-Subedi hci_send_frame(hdev, skb);
35837fedd3bbSAbhishek Pandit-Subedi
35847fedd3bbSAbhishek Pandit-Subedi conn->sent++;
35857fedd3bbSAbhishek Pandit-Subedi if (conn->sent == ~0)
35867fedd3bbSAbhishek Pandit-Subedi conn->sent = 0;
35877fedd3bbSAbhishek Pandit-Subedi }
35887fedd3bbSAbhishek Pandit-Subedi }
35897fedd3bbSAbhishek Pandit-Subedi }
35907fedd3bbSAbhishek Pandit-Subedi
hci_sched_esco(struct hci_dev * hdev)35917fedd3bbSAbhishek Pandit-Subedi static void hci_sched_esco(struct hci_dev *hdev)
35927fedd3bbSAbhishek Pandit-Subedi {
35937fedd3bbSAbhishek Pandit-Subedi struct hci_conn *conn;
35947fedd3bbSAbhishek Pandit-Subedi struct sk_buff *skb;
35957fedd3bbSAbhishek Pandit-Subedi int quote;
35967fedd3bbSAbhishek Pandit-Subedi
35977fedd3bbSAbhishek Pandit-Subedi BT_DBG("%s", hdev->name);
35987fedd3bbSAbhishek Pandit-Subedi
35997fedd3bbSAbhishek Pandit-Subedi if (!hci_conn_num(hdev, ESCO_LINK))
36007fedd3bbSAbhishek Pandit-Subedi return;
36017fedd3bbSAbhishek Pandit-Subedi
36027fedd3bbSAbhishek Pandit-Subedi while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK,
36037fedd3bbSAbhishek Pandit-Subedi "e))) {
36047fedd3bbSAbhishek Pandit-Subedi while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
36057fedd3bbSAbhishek Pandit-Subedi BT_DBG("skb %p len %d", skb, skb->len);
36067fedd3bbSAbhishek Pandit-Subedi hci_send_frame(hdev, skb);
36077fedd3bbSAbhishek Pandit-Subedi
36087fedd3bbSAbhishek Pandit-Subedi conn->sent++;
36097fedd3bbSAbhishek Pandit-Subedi if (conn->sent == ~0)
36107fedd3bbSAbhishek Pandit-Subedi conn->sent = 0;
36117fedd3bbSAbhishek Pandit-Subedi }
36127fedd3bbSAbhishek Pandit-Subedi }
36137fedd3bbSAbhishek Pandit-Subedi }
36147fedd3bbSAbhishek Pandit-Subedi
hci_sched_acl_pkt(struct hci_dev * hdev)36156039aa73SGustavo Padovan static void hci_sched_acl_pkt(struct hci_dev *hdev)
361663d2bc1bSAndrei Emeltchenko {
361763d2bc1bSAndrei Emeltchenko unsigned int cnt = hdev->acl_cnt;
361863d2bc1bSAndrei Emeltchenko struct hci_chan *chan;
361963d2bc1bSAndrei Emeltchenko struct sk_buff *skb;
362063d2bc1bSAndrei Emeltchenko int quote;
362163d2bc1bSAndrei Emeltchenko
3622116523c8SLuiz Augusto von Dentz __check_timeout(hdev, cnt, ACL_LINK);
362304837f64SMarcel Holtmann
362473d80debSLuiz Augusto von Dentz while (hdev->acl_cnt &&
362573d80debSLuiz Augusto von Dentz (chan = hci_chan_sent(hdev, ACL_LINK, "e))) {
3626ec1cce24SLuiz Augusto von Dentz u32 priority = (skb_peek(&chan->data_q))->priority;
3627ec1cce24SLuiz Augusto von Dentz while (quote-- && (skb = skb_peek(&chan->data_q))) {
362873d80debSLuiz Augusto von Dentz BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
362973d80debSLuiz Augusto von Dentz skb->len, skb->priority);
363073d80debSLuiz Augusto von Dentz
3631ec1cce24SLuiz Augusto von Dentz /* Stop if priority has changed */
3632ec1cce24SLuiz Augusto von Dentz if (skb->priority < priority)
3633ec1cce24SLuiz Augusto von Dentz break;
3634ec1cce24SLuiz Augusto von Dentz
3635ec1cce24SLuiz Augusto von Dentz skb = skb_dequeue(&chan->data_q);
3636ec1cce24SLuiz Augusto von Dentz
363773d80debSLuiz Augusto von Dentz hci_conn_enter_active_mode(chan->conn,
363873d80debSLuiz Augusto von Dentz bt_cb(skb)->force_active);
363904837f64SMarcel Holtmann
364057d17d70SMarcel Holtmann hci_send_frame(hdev, skb);
36411da177e4SLinus Torvalds hdev->acl_last_tx = jiffies;
36421da177e4SLinus Torvalds
36431da177e4SLinus Torvalds hdev->acl_cnt--;
364473d80debSLuiz Augusto von Dentz chan->sent++;
364573d80debSLuiz Augusto von Dentz chan->conn->sent++;
36467fedd3bbSAbhishek Pandit-Subedi
36477fedd3bbSAbhishek Pandit-Subedi /* Send pending SCO packets right away */
36487fedd3bbSAbhishek Pandit-Subedi hci_sched_sco(hdev);
36497fedd3bbSAbhishek Pandit-Subedi hci_sched_esco(hdev);
36501da177e4SLinus Torvalds }
36511da177e4SLinus Torvalds }
365202b20f0bSLuiz Augusto von Dentz
365302b20f0bSLuiz Augusto von Dentz if (cnt != hdev->acl_cnt)
365402b20f0bSLuiz Augusto von Dentz hci_prio_recalculate(hdev, ACL_LINK);
36551da177e4SLinus Torvalds }
36561da177e4SLinus Torvalds
hci_sched_acl(struct hci_dev * hdev)36576039aa73SGustavo Padovan static void hci_sched_acl(struct hci_dev *hdev)
3658b71d385aSAndrei Emeltchenko {
3659b71d385aSAndrei Emeltchenko BT_DBG("%s", hdev->name);
3660b71d385aSAndrei Emeltchenko
3661bd1eb66bSAndrei Emeltchenko /* No ACL link over BR/EDR controller */
36625af2e235SLuiz Augusto von Dentz if (!hci_conn_num(hdev, ACL_LINK))
3663bd1eb66bSAndrei Emeltchenko return;
3664bd1eb66bSAndrei Emeltchenko
3665b71d385aSAndrei Emeltchenko hci_sched_acl_pkt(hdev);
3666b71d385aSAndrei Emeltchenko }
3667b71d385aSAndrei Emeltchenko
hci_sched_le(struct hci_dev * hdev)36686039aa73SGustavo Padovan static void hci_sched_le(struct hci_dev *hdev)
36696ed58ec5SVille Tervo {
367073d80debSLuiz Augusto von Dentz struct hci_chan *chan;
36716ed58ec5SVille Tervo struct sk_buff *skb;
367202b20f0bSLuiz Augusto von Dentz int quote, cnt, tmp;
36736ed58ec5SVille Tervo
36746ed58ec5SVille Tervo BT_DBG("%s", hdev->name);
36756ed58ec5SVille Tervo
367652087a79SLuiz Augusto von Dentz if (!hci_conn_num(hdev, LE_LINK))
367752087a79SLuiz Augusto von Dentz return;
367852087a79SLuiz Augusto von Dentz
36796ed58ec5SVille Tervo cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
36801b1d29e5SLuiz Augusto von Dentz
3681116523c8SLuiz Augusto von Dentz __check_timeout(hdev, cnt, LE_LINK);
36821b1d29e5SLuiz Augusto von Dentz
368302b20f0bSLuiz Augusto von Dentz tmp = cnt;
368473d80debSLuiz Augusto von Dentz while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) {
3685ec1cce24SLuiz Augusto von Dentz u32 priority = (skb_peek(&chan->data_q))->priority;
3686ec1cce24SLuiz Augusto von Dentz while (quote-- && (skb = skb_peek(&chan->data_q))) {
368773d80debSLuiz Augusto von Dentz BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
368873d80debSLuiz Augusto von Dentz skb->len, skb->priority);
36896ed58ec5SVille Tervo
3690ec1cce24SLuiz Augusto von Dentz /* Stop if priority has changed */
3691ec1cce24SLuiz Augusto von Dentz if (skb->priority < priority)
3692ec1cce24SLuiz Augusto von Dentz break;
3693ec1cce24SLuiz Augusto von Dentz
3694ec1cce24SLuiz Augusto von Dentz skb = skb_dequeue(&chan->data_q);
3695ec1cce24SLuiz Augusto von Dentz
369657d17d70SMarcel Holtmann hci_send_frame(hdev, skb);
36976ed58ec5SVille Tervo hdev->le_last_tx = jiffies;
36986ed58ec5SVille Tervo
36996ed58ec5SVille Tervo cnt--;
370073d80debSLuiz Augusto von Dentz chan->sent++;
370173d80debSLuiz Augusto von Dentz chan->conn->sent++;
37027fedd3bbSAbhishek Pandit-Subedi
37037fedd3bbSAbhishek Pandit-Subedi /* Send pending SCO packets right away */
37047fedd3bbSAbhishek Pandit-Subedi hci_sched_sco(hdev);
37057fedd3bbSAbhishek Pandit-Subedi hci_sched_esco(hdev);
37066ed58ec5SVille Tervo }
37076ed58ec5SVille Tervo }
370873d80debSLuiz Augusto von Dentz
37096ed58ec5SVille Tervo if (hdev->le_pkts)
37106ed58ec5SVille Tervo hdev->le_cnt = cnt;
37116ed58ec5SVille Tervo else
37126ed58ec5SVille Tervo hdev->acl_cnt = cnt;
371302b20f0bSLuiz Augusto von Dentz
371402b20f0bSLuiz Augusto von Dentz if (cnt != tmp)
371502b20f0bSLuiz Augusto von Dentz hci_prio_recalculate(hdev, LE_LINK);
37166ed58ec5SVille Tervo }
37176ed58ec5SVille Tervo
371826afbd82SLuiz Augusto von Dentz /* Schedule CIS */
hci_sched_iso(struct hci_dev * hdev)371926afbd82SLuiz Augusto von Dentz static void hci_sched_iso(struct hci_dev *hdev)
372026afbd82SLuiz Augusto von Dentz {
372126afbd82SLuiz Augusto von Dentz struct hci_conn *conn;
372226afbd82SLuiz Augusto von Dentz struct sk_buff *skb;
372326afbd82SLuiz Augusto von Dentz int quote, *cnt;
372426afbd82SLuiz Augusto von Dentz
372526afbd82SLuiz Augusto von Dentz BT_DBG("%s", hdev->name);
372626afbd82SLuiz Augusto von Dentz
372726afbd82SLuiz Augusto von Dentz if (!hci_conn_num(hdev, ISO_LINK))
372826afbd82SLuiz Augusto von Dentz return;
372926afbd82SLuiz Augusto von Dentz
373026afbd82SLuiz Augusto von Dentz cnt = hdev->iso_pkts ? &hdev->iso_cnt :
373126afbd82SLuiz Augusto von Dentz hdev->le_pkts ? &hdev->le_cnt : &hdev->acl_cnt;
373226afbd82SLuiz Augusto von Dentz while (*cnt && (conn = hci_low_sent(hdev, ISO_LINK, "e))) {
373326afbd82SLuiz Augusto von Dentz while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
373426afbd82SLuiz Augusto von Dentz BT_DBG("skb %p len %d", skb, skb->len);
373526afbd82SLuiz Augusto von Dentz hci_send_frame(hdev, skb);
373626afbd82SLuiz Augusto von Dentz
373726afbd82SLuiz Augusto von Dentz conn->sent++;
373826afbd82SLuiz Augusto von Dentz if (conn->sent == ~0)
373926afbd82SLuiz Augusto von Dentz conn->sent = 0;
374026afbd82SLuiz Augusto von Dentz (*cnt)--;
374126afbd82SLuiz Augusto von Dentz }
374226afbd82SLuiz Augusto von Dentz }
374326afbd82SLuiz Augusto von Dentz }
374426afbd82SLuiz Augusto von Dentz
hci_tx_work(struct work_struct * work)37453eff45eaSGustavo F. Padovan static void hci_tx_work(struct work_struct *work)
37461da177e4SLinus Torvalds {
37473eff45eaSGustavo F. Padovan struct hci_dev *hdev = container_of(work, struct hci_dev, tx_work);
37481da177e4SLinus Torvalds struct sk_buff *skb;
37491da177e4SLinus Torvalds
375026afbd82SLuiz Augusto von Dentz BT_DBG("%s acl %d sco %d le %d iso %d", hdev->name, hdev->acl_cnt,
375126afbd82SLuiz Augusto von Dentz hdev->sco_cnt, hdev->le_cnt, hdev->iso_cnt);
37521da177e4SLinus Torvalds
3753d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
37541da177e4SLinus Torvalds /* Schedule queues and send stuff to HCI driver */
37551da177e4SLinus Torvalds hci_sched_sco(hdev);
3756b6a0dc82SMarcel Holtmann hci_sched_esco(hdev);
375726afbd82SLuiz Augusto von Dentz hci_sched_iso(hdev);
37587fedd3bbSAbhishek Pandit-Subedi hci_sched_acl(hdev);
37596ed58ec5SVille Tervo hci_sched_le(hdev);
376052de599eSMarcel Holtmann }
37616ed58ec5SVille Tervo
37621da177e4SLinus Torvalds /* Send next queued raw (unknown type) packet */
37631da177e4SLinus Torvalds while ((skb = skb_dequeue(&hdev->raw_q)))
376457d17d70SMarcel Holtmann hci_send_frame(hdev, skb);
37651da177e4SLinus Torvalds }
37661da177e4SLinus Torvalds
376725985edcSLucas De Marchi /* ----- HCI RX task (incoming data processing) ----- */
37681da177e4SLinus Torvalds
37691da177e4SLinus Torvalds /* ACL data packet */
hci_acldata_packet(struct hci_dev * hdev,struct sk_buff * skb)37706039aa73SGustavo Padovan static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
37711da177e4SLinus Torvalds {
37721da177e4SLinus Torvalds struct hci_acl_hdr *hdr = (void *) skb->data;
37731da177e4SLinus Torvalds struct hci_conn *conn;
37741da177e4SLinus Torvalds __u16 handle, flags;
37751da177e4SLinus Torvalds
37761da177e4SLinus Torvalds skb_pull(skb, HCI_ACL_HDR_SIZE);
37771da177e4SLinus Torvalds
37781da177e4SLinus Torvalds handle = __le16_to_cpu(hdr->handle);
37791da177e4SLinus Torvalds flags = hci_flags(handle);
37801da177e4SLinus Torvalds handle = hci_handle(handle);
37811da177e4SLinus Torvalds
3782f0e09510SAndrei Emeltchenko BT_DBG("%s len %d handle 0x%4.4x flags 0x%4.4x", hdev->name, skb->len,
3783a8c5fb1aSGustavo Padovan handle, flags);
37841da177e4SLinus Torvalds
37851da177e4SLinus Torvalds hdev->stat.acl_rx++;
37861da177e4SLinus Torvalds
37871da177e4SLinus Torvalds hci_dev_lock(hdev);
37881da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle);
37891da177e4SLinus Torvalds hci_dev_unlock(hdev);
37901da177e4SLinus Torvalds
37911da177e4SLinus Torvalds if (conn) {
379265983fc7SMat Martineau hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
379304837f64SMarcel Holtmann
37941da177e4SLinus Torvalds /* Send to upper protocol */
3795686ebf28SUlisses Furquim l2cap_recv_acldata(conn, skb, flags);
37961da177e4SLinus Torvalds return;
37971da177e4SLinus Torvalds } else {
37982064ee33SMarcel Holtmann bt_dev_err(hdev, "ACL packet for unknown connection handle %d",
37992064ee33SMarcel Holtmann handle);
38001da177e4SLinus Torvalds }
38011da177e4SLinus Torvalds
38021da177e4SLinus Torvalds kfree_skb(skb);
38031da177e4SLinus Torvalds }
38041da177e4SLinus Torvalds
38051da177e4SLinus Torvalds /* SCO data packet */
hci_scodata_packet(struct hci_dev * hdev,struct sk_buff * skb)38066039aa73SGustavo Padovan static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
38071da177e4SLinus Torvalds {
38081da177e4SLinus Torvalds struct hci_sco_hdr *hdr = (void *) skb->data;
38091da177e4SLinus Torvalds struct hci_conn *conn;
3810debdedf2SMarcel Holtmann __u16 handle, flags;
38111da177e4SLinus Torvalds
38121da177e4SLinus Torvalds skb_pull(skb, HCI_SCO_HDR_SIZE);
38131da177e4SLinus Torvalds
38141da177e4SLinus Torvalds handle = __le16_to_cpu(hdr->handle);
3815debdedf2SMarcel Holtmann flags = hci_flags(handle);
3816debdedf2SMarcel Holtmann handle = hci_handle(handle);
38171da177e4SLinus Torvalds
3818debdedf2SMarcel Holtmann BT_DBG("%s len %d handle 0x%4.4x flags 0x%4.4x", hdev->name, skb->len,
3819debdedf2SMarcel Holtmann handle, flags);
38201da177e4SLinus Torvalds
38211da177e4SLinus Torvalds hdev->stat.sco_rx++;
38221da177e4SLinus Torvalds
38231da177e4SLinus Torvalds hci_dev_lock(hdev);
38241da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle);
38251da177e4SLinus Torvalds hci_dev_unlock(hdev);
38261da177e4SLinus Torvalds
38271da177e4SLinus Torvalds if (conn) {
38281da177e4SLinus Torvalds /* Send to upper protocol */
38293f19ffb2SLuiz Augusto von Dentz hci_skb_pkt_status(skb) = flags & 0x03;
3830686ebf28SUlisses Furquim sco_recv_scodata(conn, skb);
38311da177e4SLinus Torvalds return;
38321da177e4SLinus Torvalds } else {
38332d4b37b6SLuiz Augusto von Dentz bt_dev_err_ratelimited(hdev, "SCO packet for unknown connection handle %d",
38342064ee33SMarcel Holtmann handle);
38351da177e4SLinus Torvalds }
38361da177e4SLinus Torvalds
38371da177e4SLinus Torvalds kfree_skb(skb);
38381da177e4SLinus Torvalds }
38391da177e4SLinus Torvalds
hci_isodata_packet(struct hci_dev * hdev,struct sk_buff * skb)384026afbd82SLuiz Augusto von Dentz static void hci_isodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
384126afbd82SLuiz Augusto von Dentz {
384226afbd82SLuiz Augusto von Dentz struct hci_iso_hdr *hdr;
384326afbd82SLuiz Augusto von Dentz struct hci_conn *conn;
384426afbd82SLuiz Augusto von Dentz __u16 handle, flags;
384526afbd82SLuiz Augusto von Dentz
384626afbd82SLuiz Augusto von Dentz hdr = skb_pull_data(skb, sizeof(*hdr));
384726afbd82SLuiz Augusto von Dentz if (!hdr) {
384826afbd82SLuiz Augusto von Dentz bt_dev_err(hdev, "ISO packet too small");
384926afbd82SLuiz Augusto von Dentz goto drop;
385026afbd82SLuiz Augusto von Dentz }
385126afbd82SLuiz Augusto von Dentz
385226afbd82SLuiz Augusto von Dentz handle = __le16_to_cpu(hdr->handle);
385326afbd82SLuiz Augusto von Dentz flags = hci_flags(handle);
385426afbd82SLuiz Augusto von Dentz handle = hci_handle(handle);
385526afbd82SLuiz Augusto von Dentz
385626afbd82SLuiz Augusto von Dentz bt_dev_dbg(hdev, "len %d handle 0x%4.4x flags 0x%4.4x", skb->len,
385726afbd82SLuiz Augusto von Dentz handle, flags);
385826afbd82SLuiz Augusto von Dentz
385926afbd82SLuiz Augusto von Dentz hci_dev_lock(hdev);
386026afbd82SLuiz Augusto von Dentz conn = hci_conn_hash_lookup_handle(hdev, handle);
386126afbd82SLuiz Augusto von Dentz hci_dev_unlock(hdev);
386226afbd82SLuiz Augusto von Dentz
386326afbd82SLuiz Augusto von Dentz if (!conn) {
386426afbd82SLuiz Augusto von Dentz bt_dev_err(hdev, "ISO packet for unknown connection handle %d",
386526afbd82SLuiz Augusto von Dentz handle);
3866ccf74f23SLuiz Augusto von Dentz goto drop;
386726afbd82SLuiz Augusto von Dentz }
386826afbd82SLuiz Augusto von Dentz
3869ccf74f23SLuiz Augusto von Dentz /* Send to upper protocol */
3870ccf74f23SLuiz Augusto von Dentz iso_recv(conn, skb, flags);
3871ccf74f23SLuiz Augusto von Dentz return;
3872ccf74f23SLuiz Augusto von Dentz
387326afbd82SLuiz Augusto von Dentz drop:
387426afbd82SLuiz Augusto von Dentz kfree_skb(skb);
387526afbd82SLuiz Augusto von Dentz }
387626afbd82SLuiz Augusto von Dentz
hci_req_is_complete(struct hci_dev * hdev)38779238f36aSJohan Hedberg static bool hci_req_is_complete(struct hci_dev *hdev)
38789238f36aSJohan Hedberg {
38799238f36aSJohan Hedberg struct sk_buff *skb;
38809238f36aSJohan Hedberg
38819238f36aSJohan Hedberg skb = skb_peek(&hdev->cmd_q);
38829238f36aSJohan Hedberg if (!skb)
38839238f36aSJohan Hedberg return true;
38849238f36aSJohan Hedberg
388544d27137SJohan Hedberg return (bt_cb(skb)->hci.req_flags & HCI_REQ_START);
38869238f36aSJohan Hedberg }
38879238f36aSJohan Hedberg
hci_resend_last(struct hci_dev * hdev)388842c6b129SJohan Hedberg static void hci_resend_last(struct hci_dev *hdev)
388942c6b129SJohan Hedberg {
389042c6b129SJohan Hedberg struct hci_command_hdr *sent;
389142c6b129SJohan Hedberg struct sk_buff *skb;
389242c6b129SJohan Hedberg u16 opcode;
389342c6b129SJohan Hedberg
389442c6b129SJohan Hedberg if (!hdev->sent_cmd)
389542c6b129SJohan Hedberg return;
389642c6b129SJohan Hedberg
389742c6b129SJohan Hedberg sent = (void *) hdev->sent_cmd->data;
389842c6b129SJohan Hedberg opcode = __le16_to_cpu(sent->opcode);
389942c6b129SJohan Hedberg if (opcode == HCI_OP_RESET)
390042c6b129SJohan Hedberg return;
390142c6b129SJohan Hedberg
390242c6b129SJohan Hedberg skb = skb_clone(hdev->sent_cmd, GFP_KERNEL);
390342c6b129SJohan Hedberg if (!skb)
390442c6b129SJohan Hedberg return;
390542c6b129SJohan Hedberg
390642c6b129SJohan Hedberg skb_queue_head(&hdev->cmd_q, skb);
390742c6b129SJohan Hedberg queue_work(hdev->workqueue, &hdev->cmd_work);
390842c6b129SJohan Hedberg }
390942c6b129SJohan Hedberg
hci_req_cmd_complete(struct hci_dev * hdev,u16 opcode,u8 status,hci_req_complete_t * req_complete,hci_req_complete_skb_t * req_complete_skb)3910e6214487SJohan Hedberg void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
3911e6214487SJohan Hedberg hci_req_complete_t *req_complete,
3912e6214487SJohan Hedberg hci_req_complete_skb_t *req_complete_skb)
39139238f36aSJohan Hedberg {
39149238f36aSJohan Hedberg struct sk_buff *skb;
39159238f36aSJohan Hedberg unsigned long flags;
39169238f36aSJohan Hedberg
39179238f36aSJohan Hedberg BT_DBG("opcode 0x%04x status 0x%02x", opcode, status);
39189238f36aSJohan Hedberg
391942c6b129SJohan Hedberg /* If the completed command doesn't match the last one that was
392042c6b129SJohan Hedberg * sent we need to do special handling of it.
39219238f36aSJohan Hedberg */
392242c6b129SJohan Hedberg if (!hci_sent_cmd_data(hdev, opcode)) {
392342c6b129SJohan Hedberg /* Some CSR based controllers generate a spontaneous
392442c6b129SJohan Hedberg * reset complete event during init and any pending
392542c6b129SJohan Hedberg * command will never be completed. In such a case we
392642c6b129SJohan Hedberg * need to resend whatever was the last sent
392742c6b129SJohan Hedberg * command.
392842c6b129SJohan Hedberg */
392942c6b129SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && opcode == HCI_OP_RESET)
393042c6b129SJohan Hedberg hci_resend_last(hdev);
393142c6b129SJohan Hedberg
39329238f36aSJohan Hedberg return;
393342c6b129SJohan Hedberg }
39349238f36aSJohan Hedberg
3935f80c5dadSJoão Paulo Rechi Vita /* If we reach this point this event matches the last command sent */
3936f80c5dadSJoão Paulo Rechi Vita hci_dev_clear_flag(hdev, HCI_CMD_PENDING);
3937f80c5dadSJoão Paulo Rechi Vita
39389238f36aSJohan Hedberg /* If the command succeeded and there's still more commands in
39399238f36aSJohan Hedberg * this request the request is not yet complete.
39409238f36aSJohan Hedberg */
39419238f36aSJohan Hedberg if (!status && !hci_req_is_complete(hdev))
39429238f36aSJohan Hedberg return;
39439238f36aSJohan Hedberg
39442af7aa66SLuiz Augusto von Dentz skb = hdev->req_skb;
39452af7aa66SLuiz Augusto von Dentz
39469238f36aSJohan Hedberg /* If this was the last command in a request the complete
39472af7aa66SLuiz Augusto von Dentz * callback would be found in hdev->req_skb instead of the
39489238f36aSJohan Hedberg * command queue (hdev->cmd_q).
39499238f36aSJohan Hedberg */
39502af7aa66SLuiz Augusto von Dentz if (skb && bt_cb(skb)->hci.req_flags & HCI_REQ_SKB) {
39512af7aa66SLuiz Augusto von Dentz *req_complete_skb = bt_cb(skb)->hci.req_complete_skb;
3952e6214487SJohan Hedberg return;
39539238f36aSJohan Hedberg }
3954e6214487SJohan Hedberg
39552af7aa66SLuiz Augusto von Dentz if (skb && bt_cb(skb)->hci.req_complete) {
39562af7aa66SLuiz Augusto von Dentz *req_complete = bt_cb(skb)->hci.req_complete;
3957e6214487SJohan Hedberg return;
395853e21fbcSJohan Hedberg }
39599238f36aSJohan Hedberg
39609238f36aSJohan Hedberg /* Remove all pending commands belonging to this request */
39619238f36aSJohan Hedberg spin_lock_irqsave(&hdev->cmd_q.lock, flags);
39629238f36aSJohan Hedberg while ((skb = __skb_dequeue(&hdev->cmd_q))) {
396344d27137SJohan Hedberg if (bt_cb(skb)->hci.req_flags & HCI_REQ_START) {
39649238f36aSJohan Hedberg __skb_queue_head(&hdev->cmd_q, skb);
39659238f36aSJohan Hedberg break;
39669238f36aSJohan Hedberg }
39679238f36aSJohan Hedberg
39683bd7594eSDouglas Anderson if (bt_cb(skb)->hci.req_flags & HCI_REQ_SKB)
3969242c0ebdSMarcel Holtmann *req_complete_skb = bt_cb(skb)->hci.req_complete_skb;
39703bd7594eSDouglas Anderson else
39713bd7594eSDouglas Anderson *req_complete = bt_cb(skb)->hci.req_complete;
397239c1eb6fSYang Yingliang dev_kfree_skb_irq(skb);
39739238f36aSJohan Hedberg }
39749238f36aSJohan Hedberg spin_unlock_irqrestore(&hdev->cmd_q.lock, flags);
39759238f36aSJohan Hedberg }
39769238f36aSJohan Hedberg
hci_rx_work(struct work_struct * work)3977b78752ccSMarcel Holtmann static void hci_rx_work(struct work_struct *work)
39781da177e4SLinus Torvalds {
3979b78752ccSMarcel Holtmann struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work);
39801da177e4SLinus Torvalds struct sk_buff *skb;
39811da177e4SLinus Torvalds
39821da177e4SLinus Torvalds BT_DBG("%s", hdev->name);
39831da177e4SLinus Torvalds
39849f30de9eSTamas Koczka /* The kcov_remote functions used for collecting packet parsing
39859f30de9eSTamas Koczka * coverage information from this background thread and associate
39869f30de9eSTamas Koczka * the coverage with the syscall's thread which originally injected
39879f30de9eSTamas Koczka * the packet. This helps fuzzing the kernel.
39889f30de9eSTamas Koczka */
39899f30de9eSTamas Koczka for (; (skb = skb_dequeue(&hdev->rx_q)); kcov_remote_stop()) {
39909f30de9eSTamas Koczka kcov_remote_start_common(skb_get_kcov_handle(skb));
39919f30de9eSTamas Koczka
3992cd82e61cSMarcel Holtmann /* Send copy to monitor */
3993cd82e61cSMarcel Holtmann hci_send_to_monitor(hdev, skb);
3994cd82e61cSMarcel Holtmann
39951da177e4SLinus Torvalds if (atomic_read(&hdev->promisc)) {
39961da177e4SLinus Torvalds /* Send copy to the sockets */
3997470fe1b5SMarcel Holtmann hci_send_to_sock(hdev, skb);
39981da177e4SLinus Torvalds }
39991da177e4SLinus Torvalds
4000eb8c101eSMattijs Korpershoek /* If the device has been opened in HCI_USER_CHANNEL,
4001eb8c101eSMattijs Korpershoek * the userspace has exclusive access to device.
4002eb8c101eSMattijs Korpershoek * When device is HCI_INIT, we still need to process
4003eb8c101eSMattijs Korpershoek * the data packets to the driver in order
4004eb8c101eSMattijs Korpershoek * to complete its setup().
4005eb8c101eSMattijs Korpershoek */
4006eb8c101eSMattijs Korpershoek if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
4007eb8c101eSMattijs Korpershoek !test_bit(HCI_INIT, &hdev->flags)) {
40081da177e4SLinus Torvalds kfree_skb(skb);
40091da177e4SLinus Torvalds continue;
40101da177e4SLinus Torvalds }
40111da177e4SLinus Torvalds
40121da177e4SLinus Torvalds if (test_bit(HCI_INIT, &hdev->flags)) {
40131da177e4SLinus Torvalds /* Don't process data packets in this states. */
4014d79f34e3SMarcel Holtmann switch (hci_skb_pkt_type(skb)) {
40151da177e4SLinus Torvalds case HCI_ACLDATA_PKT:
40161da177e4SLinus Torvalds case HCI_SCODATA_PKT:
4017cc974003SMarcel Holtmann case HCI_ISODATA_PKT:
40181da177e4SLinus Torvalds kfree_skb(skb);
40191da177e4SLinus Torvalds continue;
40203ff50b79SStephen Hemminger }
40211da177e4SLinus Torvalds }
40221da177e4SLinus Torvalds
40231da177e4SLinus Torvalds /* Process frame */
4024d79f34e3SMarcel Holtmann switch (hci_skb_pkt_type(skb)) {
40251da177e4SLinus Torvalds case HCI_EVENT_PKT:
4026b78752ccSMarcel Holtmann BT_DBG("%s Event packet", hdev->name);
40271da177e4SLinus Torvalds hci_event_packet(hdev, skb);
40281da177e4SLinus Torvalds break;
40291da177e4SLinus Torvalds
40301da177e4SLinus Torvalds case HCI_ACLDATA_PKT:
40311da177e4SLinus Torvalds BT_DBG("%s ACL data packet", hdev->name);
40321da177e4SLinus Torvalds hci_acldata_packet(hdev, skb);
40331da177e4SLinus Torvalds break;
40341da177e4SLinus Torvalds
40351da177e4SLinus Torvalds case HCI_SCODATA_PKT:
40361da177e4SLinus Torvalds BT_DBG("%s SCO data packet", hdev->name);
40371da177e4SLinus Torvalds hci_scodata_packet(hdev, skb);
40381da177e4SLinus Torvalds break;
40391da177e4SLinus Torvalds
404026afbd82SLuiz Augusto von Dentz case HCI_ISODATA_PKT:
404126afbd82SLuiz Augusto von Dentz BT_DBG("%s ISO data packet", hdev->name);
404226afbd82SLuiz Augusto von Dentz hci_isodata_packet(hdev, skb);
404326afbd82SLuiz Augusto von Dentz break;
404426afbd82SLuiz Augusto von Dentz
40451da177e4SLinus Torvalds default:
40461da177e4SLinus Torvalds kfree_skb(skb);
40471da177e4SLinus Torvalds break;
40481da177e4SLinus Torvalds }
40491da177e4SLinus Torvalds }
40501da177e4SLinus Torvalds }
40511da177e4SLinus Torvalds
hci_send_cmd_sync(struct hci_dev * hdev,struct sk_buff * skb)40520ce1229cSLuiz Augusto von Dentz static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
40530ce1229cSLuiz Augusto von Dentz {
40540ce1229cSLuiz Augusto von Dentz int err;
40550ce1229cSLuiz Augusto von Dentz
40560ce1229cSLuiz Augusto von Dentz bt_dev_dbg(hdev, "skb %p", skb);
40570ce1229cSLuiz Augusto von Dentz
40580ce1229cSLuiz Augusto von Dentz kfree_skb(hdev->sent_cmd);
40590ce1229cSLuiz Augusto von Dentz
40600ce1229cSLuiz Augusto von Dentz hdev->sent_cmd = skb_clone(skb, GFP_KERNEL);
40610ce1229cSLuiz Augusto von Dentz if (!hdev->sent_cmd) {
40620ce1229cSLuiz Augusto von Dentz skb_queue_head(&hdev->cmd_q, skb);
40630ce1229cSLuiz Augusto von Dentz queue_work(hdev->workqueue, &hdev->cmd_work);
40640ce1229cSLuiz Augusto von Dentz return;
40650ce1229cSLuiz Augusto von Dentz }
40660ce1229cSLuiz Augusto von Dentz
40670ce1229cSLuiz Augusto von Dentz err = hci_send_frame(hdev, skb);
40680ce1229cSLuiz Augusto von Dentz if (err < 0) {
40699ae3954dSLuiz Augusto von Dentz hci_cmd_sync_cancel_sync(hdev, -err);
40700ce1229cSLuiz Augusto von Dentz return;
40710ce1229cSLuiz Augusto von Dentz }
40720ce1229cSLuiz Augusto von Dentz
40732af7aa66SLuiz Augusto von Dentz if (hci_req_status_pend(hdev) &&
40742af7aa66SLuiz Augusto von Dentz !hci_dev_test_and_set_flag(hdev, HCI_CMD_PENDING)) {
40752af7aa66SLuiz Augusto von Dentz kfree_skb(hdev->req_skb);
4076a2354605SPauli Virtanen hdev->req_skb = skb_clone(hdev->sent_cmd, GFP_KERNEL);
40772af7aa66SLuiz Augusto von Dentz }
40780ce1229cSLuiz Augusto von Dentz
40790ce1229cSLuiz Augusto von Dentz atomic_dec(&hdev->cmd_cnt);
40800ce1229cSLuiz Augusto von Dentz }
40810ce1229cSLuiz Augusto von Dentz
hci_cmd_work(struct work_struct * work)4082c347b765SGustavo F. Padovan static void hci_cmd_work(struct work_struct *work)
40831da177e4SLinus Torvalds {
4084c347b765SGustavo F. Padovan struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work);
40851da177e4SLinus Torvalds struct sk_buff *skb;
40861da177e4SLinus Torvalds
40872104786bSAndrei Emeltchenko BT_DBG("%s cmd_cnt %d cmd queued %d", hdev->name,
40882104786bSAndrei Emeltchenko atomic_read(&hdev->cmd_cnt), skb_queue_len(&hdev->cmd_q));
40891da177e4SLinus Torvalds
40901da177e4SLinus Torvalds /* Send queued commands */
40915a08ecceSAndrei Emeltchenko if (atomic_read(&hdev->cmd_cnt)) {
40925a08ecceSAndrei Emeltchenko skb = skb_dequeue(&hdev->cmd_q);
40935a08ecceSAndrei Emeltchenko if (!skb)
40945a08ecceSAndrei Emeltchenko return;
40955a08ecceSAndrei Emeltchenko
40960ce1229cSLuiz Augusto von Dentz hci_send_cmd_sync(hdev, skb);
40972250abadSBenjamin Berg
4098deee93d1STetsuo Handa rcu_read_lock();
4099877afadaSSchspa Shi if (test_bit(HCI_RESET, &hdev->flags) ||
4100877afadaSSchspa Shi hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE))
410165cc2b49SMarcel Holtmann cancel_delayed_work(&hdev->cmd_timer);
41027bdb8a5cSSzymon Janc else
4103deee93d1STetsuo Handa queue_delayed_work(hdev->workqueue, &hdev->cmd_timer,
410465cc2b49SMarcel Holtmann HCI_CMD_TIMEOUT);
4105deee93d1STetsuo Handa rcu_read_unlock();
41061da177e4SLinus Torvalds }
41071da177e4SLinus Torvalds }
4108