18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci   BlueZ - Bluetooth protocol stack for Linux
38c2ecf20Sopenharmony_ci   Copyright (C) 2000-2001 Qualcomm Incorporated
48c2ecf20Sopenharmony_ci   Copyright (C) 2011 ProFUSION Embedded Systems
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci   This program is free software; you can redistribute it and/or modify
98c2ecf20Sopenharmony_ci   it under the terms of the GNU General Public License version 2 as
108c2ecf20Sopenharmony_ci   published by the Free Software Foundation;
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
138c2ecf20Sopenharmony_ci   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
148c2ecf20Sopenharmony_ci   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
158c2ecf20Sopenharmony_ci   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
168c2ecf20Sopenharmony_ci   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
178c2ecf20Sopenharmony_ci   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
188c2ecf20Sopenharmony_ci   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
198c2ecf20Sopenharmony_ci   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
228c2ecf20Sopenharmony_ci   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
238c2ecf20Sopenharmony_ci   SOFTWARE IS DISCLAIMED.
248c2ecf20Sopenharmony_ci*/
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* Bluetooth HCI core. */
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include <linux/export.h>
298c2ecf20Sopenharmony_ci#include <linux/rfkill.h>
308c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
318c2ecf20Sopenharmony_ci#include <linux/crypto.h>
328c2ecf20Sopenharmony_ci#include <linux/property.h>
338c2ecf20Sopenharmony_ci#include <linux/suspend.h>
348c2ecf20Sopenharmony_ci#include <linux/wait.h>
358c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include <net/bluetooth/bluetooth.h>
388c2ecf20Sopenharmony_ci#include <net/bluetooth/hci_core.h>
398c2ecf20Sopenharmony_ci#include <net/bluetooth/l2cap.h>
408c2ecf20Sopenharmony_ci#include <net/bluetooth/mgmt.h>
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#include "hci_request.h"
438c2ecf20Sopenharmony_ci#include "hci_debugfs.h"
448c2ecf20Sopenharmony_ci#include "smp.h"
458c2ecf20Sopenharmony_ci#include "leds.h"
468c2ecf20Sopenharmony_ci#include "msft.h"
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic void hci_rx_work(struct work_struct *work);
498c2ecf20Sopenharmony_cistatic void hci_cmd_work(struct work_struct *work);
508c2ecf20Sopenharmony_cistatic void hci_tx_work(struct work_struct *work);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* HCI device list */
538c2ecf20Sopenharmony_ciLIST_HEAD(hci_dev_list);
548c2ecf20Sopenharmony_ciDEFINE_RWLOCK(hci_dev_list_lock);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/* HCI callback list */
578c2ecf20Sopenharmony_ciLIST_HEAD(hci_cb_list);
588c2ecf20Sopenharmony_ciDEFINE_MUTEX(hci_cb_list_lock);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/* HCI ID Numbering */
618c2ecf20Sopenharmony_cistatic DEFINE_IDA(hci_index_ida);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/* ---- HCI debugfs entries ---- */
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic ssize_t dut_mode_read(struct file *file, char __user *user_buf,
668c2ecf20Sopenharmony_ci			     size_t count, loff_t *ppos)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
698c2ecf20Sopenharmony_ci	char buf[3];
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	buf[0] = hci_dev_test_flag(hdev, HCI_DUT_MODE) ? 'Y' : 'N';
728c2ecf20Sopenharmony_ci	buf[1] = '\n';
738c2ecf20Sopenharmony_ci	buf[2] = '\0';
748c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic ssize_t dut_mode_write(struct file *file, const char __user *user_buf,
788c2ecf20Sopenharmony_ci			      size_t count, loff_t *ppos)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
818c2ecf20Sopenharmony_ci	struct sk_buff *skb;
828c2ecf20Sopenharmony_ci	bool enable;
838c2ecf20Sopenharmony_ci	int err;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	if (!test_bit(HCI_UP, &hdev->flags))
868c2ecf20Sopenharmony_ci		return -ENETDOWN;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	err = kstrtobool_from_user(user_buf, count, &enable);
898c2ecf20Sopenharmony_ci	if (err)
908c2ecf20Sopenharmony_ci		return err;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	if (enable == hci_dev_test_flag(hdev, HCI_DUT_MODE))
938c2ecf20Sopenharmony_ci		return -EALREADY;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	hci_req_sync_lock(hdev);
968c2ecf20Sopenharmony_ci	if (enable)
978c2ecf20Sopenharmony_ci		skb = __hci_cmd_sync(hdev, HCI_OP_ENABLE_DUT_MODE, 0, NULL,
988c2ecf20Sopenharmony_ci				     HCI_CMD_TIMEOUT);
998c2ecf20Sopenharmony_ci	else
1008c2ecf20Sopenharmony_ci		skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL,
1018c2ecf20Sopenharmony_ci				     HCI_CMD_TIMEOUT);
1028c2ecf20Sopenharmony_ci	hci_req_sync_unlock(hdev);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	if (IS_ERR(skb))
1058c2ecf20Sopenharmony_ci		return PTR_ERR(skb);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	kfree_skb(skb);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	hci_dev_change_flag(hdev, HCI_DUT_MODE);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	return count;
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistatic const struct file_operations dut_mode_fops = {
1158c2ecf20Sopenharmony_ci	.open		= simple_open,
1168c2ecf20Sopenharmony_ci	.read		= dut_mode_read,
1178c2ecf20Sopenharmony_ci	.write		= dut_mode_write,
1188c2ecf20Sopenharmony_ci	.llseek		= default_llseek,
1198c2ecf20Sopenharmony_ci};
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic ssize_t vendor_diag_read(struct file *file, char __user *user_buf,
1228c2ecf20Sopenharmony_ci				size_t count, loff_t *ppos)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
1258c2ecf20Sopenharmony_ci	char buf[3];
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	buf[0] = hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) ? 'Y' : 'N';
1288c2ecf20Sopenharmony_ci	buf[1] = '\n';
1298c2ecf20Sopenharmony_ci	buf[2] = '\0';
1308c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic ssize_t vendor_diag_write(struct file *file, const char __user *user_buf,
1348c2ecf20Sopenharmony_ci				 size_t count, loff_t *ppos)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
1378c2ecf20Sopenharmony_ci	bool enable;
1388c2ecf20Sopenharmony_ci	int err;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	err = kstrtobool_from_user(user_buf, count, &enable);
1418c2ecf20Sopenharmony_ci	if (err)
1428c2ecf20Sopenharmony_ci		return err;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	/* When the diagnostic flags are not persistent and the transport
1458c2ecf20Sopenharmony_ci	 * is not active or in user channel operation, then there is no need
1468c2ecf20Sopenharmony_ci	 * for the vendor callback. Instead just store the desired value and
1478c2ecf20Sopenharmony_ci	 * the setting will be programmed when the controller gets powered on.
1488c2ecf20Sopenharmony_ci	 */
1498c2ecf20Sopenharmony_ci	if (test_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks) &&
1508c2ecf20Sopenharmony_ci	    (!test_bit(HCI_RUNNING, &hdev->flags) ||
1518c2ecf20Sopenharmony_ci	     hci_dev_test_flag(hdev, HCI_USER_CHANNEL)))
1528c2ecf20Sopenharmony_ci		goto done;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	hci_req_sync_lock(hdev);
1558c2ecf20Sopenharmony_ci	err = hdev->set_diag(hdev, enable);
1568c2ecf20Sopenharmony_ci	hci_req_sync_unlock(hdev);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	if (err < 0)
1598c2ecf20Sopenharmony_ci		return err;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cidone:
1628c2ecf20Sopenharmony_ci	if (enable)
1638c2ecf20Sopenharmony_ci		hci_dev_set_flag(hdev, HCI_VENDOR_DIAG);
1648c2ecf20Sopenharmony_ci	else
1658c2ecf20Sopenharmony_ci		hci_dev_clear_flag(hdev, HCI_VENDOR_DIAG);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	return count;
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic const struct file_operations vendor_diag_fops = {
1718c2ecf20Sopenharmony_ci	.open		= simple_open,
1728c2ecf20Sopenharmony_ci	.read		= vendor_diag_read,
1738c2ecf20Sopenharmony_ci	.write		= vendor_diag_write,
1748c2ecf20Sopenharmony_ci	.llseek		= default_llseek,
1758c2ecf20Sopenharmony_ci};
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic void hci_debugfs_create_basic(struct hci_dev *hdev)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev,
1808c2ecf20Sopenharmony_ci			    &dut_mode_fops);
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	if (hdev->set_diag)
1838c2ecf20Sopenharmony_ci		debugfs_create_file("vendor_diag", 0644, hdev->debugfs, hdev,
1848c2ecf20Sopenharmony_ci				    &vendor_diag_fops);
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic int hci_reset_req(struct hci_request *req, unsigned long opt)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	BT_DBG("%s %ld", req->hdev->name, opt);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	/* Reset device */
1928c2ecf20Sopenharmony_ci	set_bit(HCI_RESET, &req->hdev->flags);
1938c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_RESET, 0, NULL);
1948c2ecf20Sopenharmony_ci	return 0;
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic void bredr_init(struct hci_request *req)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	/* Read Local Supported Features */
2028c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	/* Read Local Version */
2058c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	/* Read BD Address */
2088c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL);
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic void amp_init1(struct hci_request *req)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	/* Read Local Version */
2168c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	/* Read Local Supported Commands */
2198c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	/* Read Local AMP Info */
2228c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	/* Read Data Blk size */
2258c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	/* Read Flow Control Mode */
2288c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_FLOW_CONTROL_MODE, 0, NULL);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* Read Location Data */
2318c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL);
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cistatic int amp_init2(struct hci_request *req)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	/* Read Local Supported Features. Not all AMP controllers
2378c2ecf20Sopenharmony_ci	 * support this so it's placed conditionally in the second
2388c2ecf20Sopenharmony_ci	 * stage init.
2398c2ecf20Sopenharmony_ci	 */
2408c2ecf20Sopenharmony_ci	if (req->hdev->commands[14] & 0x20)
2418c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	return 0;
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic int hci_init1_req(struct hci_request *req, unsigned long opt)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	BT_DBG("%s %ld", hdev->name, opt);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	/* Reset */
2538c2ecf20Sopenharmony_ci	if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks))
2548c2ecf20Sopenharmony_ci		hci_reset_req(req, 0);
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	switch (hdev->dev_type) {
2578c2ecf20Sopenharmony_ci	case HCI_PRIMARY:
2588c2ecf20Sopenharmony_ci		bredr_init(req);
2598c2ecf20Sopenharmony_ci		break;
2608c2ecf20Sopenharmony_ci	case HCI_AMP:
2618c2ecf20Sopenharmony_ci		amp_init1(req);
2628c2ecf20Sopenharmony_ci		break;
2638c2ecf20Sopenharmony_ci	default:
2648c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "Unknown device type %d", hdev->dev_type);
2658c2ecf20Sopenharmony_ci		break;
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	return 0;
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistatic void bredr_setup(struct hci_request *req)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	__le16 param;
2748c2ecf20Sopenharmony_ci	__u8 flt_type;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	/* Read Buffer Size (ACL mtu, max pkt, etc.) */
2778c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	/* Read Class of Device */
2808c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	/* Read Local Name */
2838c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_LOCAL_NAME, 0, NULL);
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	/* Read Voice Setting */
2868c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_VOICE_SETTING, 0, NULL);
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	/* Read Number of Supported IAC */
2898c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_NUM_SUPPORTED_IAC, 0, NULL);
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	/* Read Current IAC LAP */
2928c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_CURRENT_IAC_LAP, 0, NULL);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/* Clear Event Filters */
2958c2ecf20Sopenharmony_ci	flt_type = HCI_FLT_CLEAR_ALL;
2968c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	/* Connection accept timeout ~20 secs */
2998c2ecf20Sopenharmony_ci	param = cpu_to_le16(0x7d00);
3008c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_cistatic void le_setup(struct hci_request *req)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	/* Read LE Buffer Size */
3088c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	/* Read LE Local Supported Features */
3118c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	/* Read LE Supported States */
3148c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	/* LE-only controllers have LE implicitly enabled */
3178c2ecf20Sopenharmony_ci	if (!lmp_bredr_capable(hdev))
3188c2ecf20Sopenharmony_ci		hci_dev_set_flag(hdev, HCI_LE_ENABLED);
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic void hci_setup_event_mask(struct hci_request *req)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	/* The second byte is 0xff instead of 0x9f (two reserved bits
3268c2ecf20Sopenharmony_ci	 * disabled) since a Broadcom 1.2 dongle doesn't respond to the
3278c2ecf20Sopenharmony_ci	 * command otherwise.
3288c2ecf20Sopenharmony_ci	 */
3298c2ecf20Sopenharmony_ci	u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	/* CSR 1.1 dongles does not accept any bitfield so don't try to set
3328c2ecf20Sopenharmony_ci	 * any event mask for pre 1.2 devices.
3338c2ecf20Sopenharmony_ci	 */
3348c2ecf20Sopenharmony_ci	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
3358c2ecf20Sopenharmony_ci		return;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	if (lmp_bredr_capable(hdev)) {
3388c2ecf20Sopenharmony_ci		events[4] |= 0x01; /* Flow Specification Complete */
3398c2ecf20Sopenharmony_ci	} else {
3408c2ecf20Sopenharmony_ci		/* Use a different default for LE-only devices */
3418c2ecf20Sopenharmony_ci		memset(events, 0, sizeof(events));
3428c2ecf20Sopenharmony_ci		events[1] |= 0x20; /* Command Complete */
3438c2ecf20Sopenharmony_ci		events[1] |= 0x40; /* Command Status */
3448c2ecf20Sopenharmony_ci		events[1] |= 0x80; /* Hardware Error */
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci		/* If the controller supports the Disconnect command, enable
3478c2ecf20Sopenharmony_ci		 * the corresponding event. In addition enable packet flow
3488c2ecf20Sopenharmony_ci		 * control related events.
3498c2ecf20Sopenharmony_ci		 */
3508c2ecf20Sopenharmony_ci		if (hdev->commands[0] & 0x20) {
3518c2ecf20Sopenharmony_ci			events[0] |= 0x10; /* Disconnection Complete */
3528c2ecf20Sopenharmony_ci			events[2] |= 0x04; /* Number of Completed Packets */
3538c2ecf20Sopenharmony_ci			events[3] |= 0x02; /* Data Buffer Overflow */
3548c2ecf20Sopenharmony_ci		}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci		/* If the controller supports the Read Remote Version
3578c2ecf20Sopenharmony_ci		 * Information command, enable the corresponding event.
3588c2ecf20Sopenharmony_ci		 */
3598c2ecf20Sopenharmony_ci		if (hdev->commands[2] & 0x80)
3608c2ecf20Sopenharmony_ci			events[1] |= 0x08; /* Read Remote Version Information
3618c2ecf20Sopenharmony_ci					    * Complete
3628c2ecf20Sopenharmony_ci					    */
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci		if (hdev->le_features[0] & HCI_LE_ENCRYPTION) {
3658c2ecf20Sopenharmony_ci			events[0] |= 0x80; /* Encryption Change */
3668c2ecf20Sopenharmony_ci			events[5] |= 0x80; /* Encryption Key Refresh Complete */
3678c2ecf20Sopenharmony_ci		}
3688c2ecf20Sopenharmony_ci	}
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	if (lmp_inq_rssi_capable(hdev) ||
3718c2ecf20Sopenharmony_ci	    test_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks))
3728c2ecf20Sopenharmony_ci		events[4] |= 0x02; /* Inquiry Result with RSSI */
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	if (lmp_ext_feat_capable(hdev))
3758c2ecf20Sopenharmony_ci		events[4] |= 0x04; /* Read Remote Extended Features Complete */
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	if (lmp_esco_capable(hdev)) {
3788c2ecf20Sopenharmony_ci		events[5] |= 0x08; /* Synchronous Connection Complete */
3798c2ecf20Sopenharmony_ci		events[5] |= 0x10; /* Synchronous Connection Changed */
3808c2ecf20Sopenharmony_ci	}
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	if (lmp_sniffsubr_capable(hdev))
3838c2ecf20Sopenharmony_ci		events[5] |= 0x20; /* Sniff Subrating */
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	if (lmp_pause_enc_capable(hdev))
3868c2ecf20Sopenharmony_ci		events[5] |= 0x80; /* Encryption Key Refresh Complete */
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	if (lmp_ext_inq_capable(hdev))
3898c2ecf20Sopenharmony_ci		events[5] |= 0x40; /* Extended Inquiry Result */
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	if (lmp_no_flush_capable(hdev))
3928c2ecf20Sopenharmony_ci		events[7] |= 0x01; /* Enhanced Flush Complete */
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	if (lmp_lsto_capable(hdev))
3958c2ecf20Sopenharmony_ci		events[6] |= 0x80; /* Link Supervision Timeout Changed */
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	if (lmp_ssp_capable(hdev)) {
3988c2ecf20Sopenharmony_ci		events[6] |= 0x01;	/* IO Capability Request */
3998c2ecf20Sopenharmony_ci		events[6] |= 0x02;	/* IO Capability Response */
4008c2ecf20Sopenharmony_ci		events[6] |= 0x04;	/* User Confirmation Request */
4018c2ecf20Sopenharmony_ci		events[6] |= 0x08;	/* User Passkey Request */
4028c2ecf20Sopenharmony_ci		events[6] |= 0x10;	/* Remote OOB Data Request */
4038c2ecf20Sopenharmony_ci		events[6] |= 0x20;	/* Simple Pairing Complete */
4048c2ecf20Sopenharmony_ci		events[7] |= 0x04;	/* User Passkey Notification */
4058c2ecf20Sopenharmony_ci		events[7] |= 0x08;	/* Keypress Notification */
4068c2ecf20Sopenharmony_ci		events[7] |= 0x10;	/* Remote Host Supported
4078c2ecf20Sopenharmony_ci					 * Features Notification
4088c2ecf20Sopenharmony_ci					 */
4098c2ecf20Sopenharmony_ci	}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	if (lmp_le_capable(hdev))
4128c2ecf20Sopenharmony_ci		events[7] |= 0x20;	/* LE Meta-Event */
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_cistatic int hci_init2_req(struct hci_request *req, unsigned long opt)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	if (hdev->dev_type == HCI_AMP)
4228c2ecf20Sopenharmony_ci		return amp_init2(req);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	if (lmp_bredr_capable(hdev))
4258c2ecf20Sopenharmony_ci		bredr_setup(req);
4268c2ecf20Sopenharmony_ci	else
4278c2ecf20Sopenharmony_ci		hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	if (lmp_le_capable(hdev))
4308c2ecf20Sopenharmony_ci		le_setup(req);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	/* All Bluetooth 1.2 and later controllers should support the
4338c2ecf20Sopenharmony_ci	 * HCI command for reading the local supported commands.
4348c2ecf20Sopenharmony_ci	 *
4358c2ecf20Sopenharmony_ci	 * Unfortunately some controllers indicate Bluetooth 1.2 support,
4368c2ecf20Sopenharmony_ci	 * but do not have support for this command. If that is the case,
4378c2ecf20Sopenharmony_ci	 * the driver can quirk the behavior and skip reading the local
4388c2ecf20Sopenharmony_ci	 * supported commands.
4398c2ecf20Sopenharmony_ci	 */
4408c2ecf20Sopenharmony_ci	if (hdev->hci_ver > BLUETOOTH_VER_1_1 &&
4418c2ecf20Sopenharmony_ci	    !test_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks))
4428c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	if (lmp_ssp_capable(hdev)) {
4458c2ecf20Sopenharmony_ci		/* When SSP is available, then the host features page
4468c2ecf20Sopenharmony_ci		 * should also be available as well. However some
4478c2ecf20Sopenharmony_ci		 * controllers list the max_page as 0 as long as SSP
4488c2ecf20Sopenharmony_ci		 * has not been enabled. To achieve proper debugging
4498c2ecf20Sopenharmony_ci		 * output, force the minimum max_page to 1 at least.
4508c2ecf20Sopenharmony_ci		 */
4518c2ecf20Sopenharmony_ci		hdev->max_page = 0x01;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci		if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
4548c2ecf20Sopenharmony_ci			u8 mode = 0x01;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_WRITE_SSP_MODE,
4578c2ecf20Sopenharmony_ci				    sizeof(mode), &mode);
4588c2ecf20Sopenharmony_ci		} else {
4598c2ecf20Sopenharmony_ci			struct hci_cp_write_eir cp;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci			memset(hdev->eir, 0, sizeof(hdev->eir));
4628c2ecf20Sopenharmony_ci			memset(&cp, 0, sizeof(cp));
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
4658c2ecf20Sopenharmony_ci		}
4668c2ecf20Sopenharmony_ci	}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	if (lmp_inq_rssi_capable(hdev) ||
4698c2ecf20Sopenharmony_ci	    test_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks)) {
4708c2ecf20Sopenharmony_ci		u8 mode;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci		/* If Extended Inquiry Result events are supported, then
4738c2ecf20Sopenharmony_ci		 * they are clearly preferred over Inquiry Result with RSSI
4748c2ecf20Sopenharmony_ci		 * events.
4758c2ecf20Sopenharmony_ci		 */
4768c2ecf20Sopenharmony_ci		mode = lmp_ext_inq_capable(hdev) ? 0x02 : 0x01;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
4798c2ecf20Sopenharmony_ci	}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	if (lmp_inq_tx_pwr_capable(hdev))
4828c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	if (lmp_ext_feat_capable(hdev)) {
4858c2ecf20Sopenharmony_ci		struct hci_cp_read_local_ext_features cp;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci		cp.page = 0x01;
4888c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES,
4898c2ecf20Sopenharmony_ci			    sizeof(cp), &cp);
4908c2ecf20Sopenharmony_ci	}
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
4938c2ecf20Sopenharmony_ci		u8 enable = 1;
4948c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
4958c2ecf20Sopenharmony_ci			    &enable);
4968c2ecf20Sopenharmony_ci	}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	return 0;
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic void hci_setup_link_policy(struct hci_request *req)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
5048c2ecf20Sopenharmony_ci	struct hci_cp_write_def_link_policy cp;
5058c2ecf20Sopenharmony_ci	u16 link_policy = 0;
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	if (lmp_rswitch_capable(hdev))
5088c2ecf20Sopenharmony_ci		link_policy |= HCI_LP_RSWITCH;
5098c2ecf20Sopenharmony_ci	if (lmp_hold_capable(hdev))
5108c2ecf20Sopenharmony_ci		link_policy |= HCI_LP_HOLD;
5118c2ecf20Sopenharmony_ci	if (lmp_sniff_capable(hdev))
5128c2ecf20Sopenharmony_ci		link_policy |= HCI_LP_SNIFF;
5138c2ecf20Sopenharmony_ci	if (lmp_park_capable(hdev))
5148c2ecf20Sopenharmony_ci		link_policy |= HCI_LP_PARK;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	cp.policy = cpu_to_le16(link_policy);
5178c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
5188c2ecf20Sopenharmony_ci}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_cistatic void hci_set_le_support(struct hci_request *req)
5218c2ecf20Sopenharmony_ci{
5228c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
5238c2ecf20Sopenharmony_ci	struct hci_cp_write_le_host_supported cp;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	/* LE-only devices do not support explicit enablement */
5268c2ecf20Sopenharmony_ci	if (!lmp_bredr_capable(hdev))
5278c2ecf20Sopenharmony_ci		return;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	memset(&cp, 0, sizeof(cp));
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
5328c2ecf20Sopenharmony_ci		cp.le = 0x01;
5338c2ecf20Sopenharmony_ci		cp.simul = 0x00;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	if (cp.le != lmp_host_le_capable(hdev))
5378c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
5388c2ecf20Sopenharmony_ci			    &cp);
5398c2ecf20Sopenharmony_ci}
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_cistatic void hci_set_event_mask_page_2(struct hci_request *req)
5428c2ecf20Sopenharmony_ci{
5438c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
5448c2ecf20Sopenharmony_ci	u8 events[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
5458c2ecf20Sopenharmony_ci	bool changed = false;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	/* If Connectionless Slave Broadcast master role is supported
5488c2ecf20Sopenharmony_ci	 * enable all necessary events for it.
5498c2ecf20Sopenharmony_ci	 */
5508c2ecf20Sopenharmony_ci	if (lmp_csb_master_capable(hdev)) {
5518c2ecf20Sopenharmony_ci		events[1] |= 0x40;	/* Triggered Clock Capture */
5528c2ecf20Sopenharmony_ci		events[1] |= 0x80;	/* Synchronization Train Complete */
5538c2ecf20Sopenharmony_ci		events[2] |= 0x10;	/* Slave Page Response Timeout */
5548c2ecf20Sopenharmony_ci		events[2] |= 0x20;	/* CSB Channel Map Change */
5558c2ecf20Sopenharmony_ci		changed = true;
5568c2ecf20Sopenharmony_ci	}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	/* If Connectionless Slave Broadcast slave role is supported
5598c2ecf20Sopenharmony_ci	 * enable all necessary events for it.
5608c2ecf20Sopenharmony_ci	 */
5618c2ecf20Sopenharmony_ci	if (lmp_csb_slave_capable(hdev)) {
5628c2ecf20Sopenharmony_ci		events[2] |= 0x01;	/* Synchronization Train Received */
5638c2ecf20Sopenharmony_ci		events[2] |= 0x02;	/* CSB Receive */
5648c2ecf20Sopenharmony_ci		events[2] |= 0x04;	/* CSB Timeout */
5658c2ecf20Sopenharmony_ci		events[2] |= 0x08;	/* Truncated Page Complete */
5668c2ecf20Sopenharmony_ci		changed = true;
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	/* Enable Authenticated Payload Timeout Expired event if supported */
5708c2ecf20Sopenharmony_ci	if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING) {
5718c2ecf20Sopenharmony_ci		events[2] |= 0x80;
5728c2ecf20Sopenharmony_ci		changed = true;
5738c2ecf20Sopenharmony_ci	}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	/* Some Broadcom based controllers indicate support for Set Event
5768c2ecf20Sopenharmony_ci	 * Mask Page 2 command, but then actually do not support it. Since
5778c2ecf20Sopenharmony_ci	 * the default value is all bits set to zero, the command is only
5788c2ecf20Sopenharmony_ci	 * required if the event mask has to be changed. In case no change
5798c2ecf20Sopenharmony_ci	 * to the event mask is needed, skip this command.
5808c2ecf20Sopenharmony_ci	 */
5818c2ecf20Sopenharmony_ci	if (changed)
5828c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2,
5838c2ecf20Sopenharmony_ci			    sizeof(events), events);
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_cistatic int hci_init3_req(struct hci_request *req, unsigned long opt)
5878c2ecf20Sopenharmony_ci{
5888c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
5898c2ecf20Sopenharmony_ci	u8 p;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	hci_setup_event_mask(req);
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	if (hdev->commands[6] & 0x20 &&
5948c2ecf20Sopenharmony_ci	    !test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) {
5958c2ecf20Sopenharmony_ci		struct hci_cp_read_stored_link_key cp;
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci		bacpy(&cp.bdaddr, BDADDR_ANY);
5988c2ecf20Sopenharmony_ci		cp.read_all = 0x01;
5998c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_STORED_LINK_KEY, sizeof(cp), &cp);
6008c2ecf20Sopenharmony_ci	}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	if (hdev->commands[5] & 0x10)
6038c2ecf20Sopenharmony_ci		hci_setup_link_policy(req);
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	if (hdev->commands[8] & 0x01)
6068c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	if (hdev->commands[18] & 0x04 &&
6098c2ecf20Sopenharmony_ci	    !test_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks))
6108c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_DEF_ERR_DATA_REPORTING, 0, NULL);
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	/* Some older Broadcom based Bluetooth 1.2 controllers do not
6138c2ecf20Sopenharmony_ci	 * support the Read Page Scan Type command. Check support for
6148c2ecf20Sopenharmony_ci	 * this command in the bit mask of supported commands.
6158c2ecf20Sopenharmony_ci	 */
6168c2ecf20Sopenharmony_ci	if (hdev->commands[13] & 0x01)
6178c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	if (lmp_le_capable(hdev)) {
6208c2ecf20Sopenharmony_ci		u8 events[8];
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci		memset(events, 0, sizeof(events));
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci		if (hdev->le_features[0] & HCI_LE_ENCRYPTION)
6258c2ecf20Sopenharmony_ci			events[0] |= 0x10;	/* LE Long Term Key Request */
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci		/* If controller supports the Connection Parameters Request
6288c2ecf20Sopenharmony_ci		 * Link Layer Procedure, enable the corresponding event.
6298c2ecf20Sopenharmony_ci		 */
6308c2ecf20Sopenharmony_ci		if (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC)
6318c2ecf20Sopenharmony_ci			events[0] |= 0x20;	/* LE Remote Connection
6328c2ecf20Sopenharmony_ci						 * Parameter Request
6338c2ecf20Sopenharmony_ci						 */
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci		/* If the controller supports the Data Length Extension
6368c2ecf20Sopenharmony_ci		 * feature, enable the corresponding event.
6378c2ecf20Sopenharmony_ci		 */
6388c2ecf20Sopenharmony_ci		if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT)
6398c2ecf20Sopenharmony_ci			events[0] |= 0x40;	/* LE Data Length Change */
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci		/* If the controller supports LL Privacy feature, enable
6428c2ecf20Sopenharmony_ci		 * the corresponding event.
6438c2ecf20Sopenharmony_ci		 */
6448c2ecf20Sopenharmony_ci		if (hdev->le_features[0] & HCI_LE_LL_PRIVACY)
6458c2ecf20Sopenharmony_ci			events[1] |= 0x02;	/* LE Enhanced Connection
6468c2ecf20Sopenharmony_ci						 * Complete
6478c2ecf20Sopenharmony_ci						 */
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci		/* If the controller supports Extended Scanner Filter
6508c2ecf20Sopenharmony_ci		 * Policies, enable the correspondig event.
6518c2ecf20Sopenharmony_ci		 */
6528c2ecf20Sopenharmony_ci		if (hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY)
6538c2ecf20Sopenharmony_ci			events[1] |= 0x04;	/* LE Direct Advertising
6548c2ecf20Sopenharmony_ci						 * Report
6558c2ecf20Sopenharmony_ci						 */
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci		/* If the controller supports Channel Selection Algorithm #2
6588c2ecf20Sopenharmony_ci		 * feature, enable the corresponding event.
6598c2ecf20Sopenharmony_ci		 */
6608c2ecf20Sopenharmony_ci		if (hdev->le_features[1] & HCI_LE_CHAN_SEL_ALG2)
6618c2ecf20Sopenharmony_ci			events[2] |= 0x08;	/* LE Channel Selection
6628c2ecf20Sopenharmony_ci						 * Algorithm
6638c2ecf20Sopenharmony_ci						 */
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci		/* If the controller supports the LE Set Scan Enable command,
6668c2ecf20Sopenharmony_ci		 * enable the corresponding advertising report event.
6678c2ecf20Sopenharmony_ci		 */
6688c2ecf20Sopenharmony_ci		if (hdev->commands[26] & 0x08)
6698c2ecf20Sopenharmony_ci			events[0] |= 0x02;	/* LE Advertising Report */
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci		/* If the controller supports the LE Create Connection
6728c2ecf20Sopenharmony_ci		 * command, enable the corresponding event.
6738c2ecf20Sopenharmony_ci		 */
6748c2ecf20Sopenharmony_ci		if (hdev->commands[26] & 0x10)
6758c2ecf20Sopenharmony_ci			events[0] |= 0x01;	/* LE Connection Complete */
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci		/* If the controller supports the LE Connection Update
6788c2ecf20Sopenharmony_ci		 * command, enable the corresponding event.
6798c2ecf20Sopenharmony_ci		 */
6808c2ecf20Sopenharmony_ci		if (hdev->commands[27] & 0x04)
6818c2ecf20Sopenharmony_ci			events[0] |= 0x04;	/* LE Connection Update
6828c2ecf20Sopenharmony_ci						 * Complete
6838c2ecf20Sopenharmony_ci						 */
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci		/* If the controller supports the LE Read Remote Used Features
6868c2ecf20Sopenharmony_ci		 * command, enable the corresponding event.
6878c2ecf20Sopenharmony_ci		 */
6888c2ecf20Sopenharmony_ci		if (hdev->commands[27] & 0x20)
6898c2ecf20Sopenharmony_ci			events[0] |= 0x08;	/* LE Read Remote Used
6908c2ecf20Sopenharmony_ci						 * Features Complete
6918c2ecf20Sopenharmony_ci						 */
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci		/* If the controller supports the LE Read Local P-256
6948c2ecf20Sopenharmony_ci		 * Public Key command, enable the corresponding event.
6958c2ecf20Sopenharmony_ci		 */
6968c2ecf20Sopenharmony_ci		if (hdev->commands[34] & 0x02)
6978c2ecf20Sopenharmony_ci			events[0] |= 0x80;	/* LE Read Local P-256
6988c2ecf20Sopenharmony_ci						 * Public Key Complete
6998c2ecf20Sopenharmony_ci						 */
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci		/* If the controller supports the LE Generate DHKey
7028c2ecf20Sopenharmony_ci		 * command, enable the corresponding event.
7038c2ecf20Sopenharmony_ci		 */
7048c2ecf20Sopenharmony_ci		if (hdev->commands[34] & 0x04)
7058c2ecf20Sopenharmony_ci			events[1] |= 0x01;	/* LE Generate DHKey Complete */
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci		/* If the controller supports the LE Set Default PHY or
7088c2ecf20Sopenharmony_ci		 * LE Set PHY commands, enable the corresponding event.
7098c2ecf20Sopenharmony_ci		 */
7108c2ecf20Sopenharmony_ci		if (hdev->commands[35] & (0x20 | 0x40))
7118c2ecf20Sopenharmony_ci			events[1] |= 0x08;        /* LE PHY Update Complete */
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci		/* If the controller supports LE Set Extended Scan Parameters
7148c2ecf20Sopenharmony_ci		 * and LE Set Extended Scan Enable commands, enable the
7158c2ecf20Sopenharmony_ci		 * corresponding event.
7168c2ecf20Sopenharmony_ci		 */
7178c2ecf20Sopenharmony_ci		if (use_ext_scan(hdev))
7188c2ecf20Sopenharmony_ci			events[1] |= 0x10;	/* LE Extended Advertising
7198c2ecf20Sopenharmony_ci						 * Report
7208c2ecf20Sopenharmony_ci						 */
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci		/* If the controller supports the LE Extended Advertising
7238c2ecf20Sopenharmony_ci		 * command, enable the corresponding event.
7248c2ecf20Sopenharmony_ci		 */
7258c2ecf20Sopenharmony_ci		if (ext_adv_capable(hdev))
7268c2ecf20Sopenharmony_ci			events[2] |= 0x02;	/* LE Advertising Set
7278c2ecf20Sopenharmony_ci						 * Terminated
7288c2ecf20Sopenharmony_ci						 */
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
7318c2ecf20Sopenharmony_ci			    events);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci		/* Read LE Advertising Channel TX Power */
7348c2ecf20Sopenharmony_ci		if ((hdev->commands[25] & 0x40) && !ext_adv_capable(hdev)) {
7358c2ecf20Sopenharmony_ci			/* HCI TS spec forbids mixing of legacy and extended
7368c2ecf20Sopenharmony_ci			 * advertising commands wherein READ_ADV_TX_POWER is
7378c2ecf20Sopenharmony_ci			 * also included. So do not call it if extended adv
7388c2ecf20Sopenharmony_ci			 * is supported otherwise controller will return
7398c2ecf20Sopenharmony_ci			 * COMMAND_DISALLOWED for extended commands.
7408c2ecf20Sopenharmony_ci			 */
7418c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
7428c2ecf20Sopenharmony_ci		}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci		if (hdev->commands[26] & 0x40) {
7458c2ecf20Sopenharmony_ci			/* Read LE Accept List Size */
7468c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_LE_READ_ACCEPT_LIST_SIZE,
7478c2ecf20Sopenharmony_ci				    0, NULL);
7488c2ecf20Sopenharmony_ci		}
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci		if (hdev->commands[26] & 0x80) {
7518c2ecf20Sopenharmony_ci			/* Clear LE Accept List */
7528c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_LE_CLEAR_ACCEPT_LIST, 0, NULL);
7538c2ecf20Sopenharmony_ci		}
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci		if (hdev->commands[34] & 0x40) {
7568c2ecf20Sopenharmony_ci			/* Read LE Resolving List Size */
7578c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_LE_READ_RESOLV_LIST_SIZE,
7588c2ecf20Sopenharmony_ci				    0, NULL);
7598c2ecf20Sopenharmony_ci		}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci		if (hdev->commands[34] & 0x20) {
7628c2ecf20Sopenharmony_ci			/* Clear LE Resolving List */
7638c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_LE_CLEAR_RESOLV_LIST, 0, NULL);
7648c2ecf20Sopenharmony_ci		}
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci		if (hdev->commands[35] & 0x04) {
7678c2ecf20Sopenharmony_ci			__le16 rpa_timeout = cpu_to_le16(hdev->rpa_timeout);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci			/* Set RPA timeout */
7708c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_LE_SET_RPA_TIMEOUT, 2,
7718c2ecf20Sopenharmony_ci				    &rpa_timeout);
7728c2ecf20Sopenharmony_ci		}
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci		if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) {
7758c2ecf20Sopenharmony_ci			/* Read LE Maximum Data Length */
7768c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_LE_READ_MAX_DATA_LEN, 0, NULL);
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci			/* Read LE Suggested Default Data Length */
7798c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_LE_READ_DEF_DATA_LEN, 0, NULL);
7808c2ecf20Sopenharmony_ci		}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci		if (ext_adv_capable(hdev)) {
7838c2ecf20Sopenharmony_ci			/* Read LE Number of Supported Advertising Sets */
7848c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS,
7858c2ecf20Sopenharmony_ci				    0, NULL);
7868c2ecf20Sopenharmony_ci		}
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci		hci_set_le_support(req);
7898c2ecf20Sopenharmony_ci	}
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	/* Read features beyond page 1 if available */
7928c2ecf20Sopenharmony_ci	for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
7938c2ecf20Sopenharmony_ci		struct hci_cp_read_local_ext_features cp;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci		cp.page = p;
7968c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES,
7978c2ecf20Sopenharmony_ci			    sizeof(cp), &cp);
7988c2ecf20Sopenharmony_ci	}
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	return 0;
8018c2ecf20Sopenharmony_ci}
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_cistatic int hci_init4_req(struct hci_request *req, unsigned long opt)
8048c2ecf20Sopenharmony_ci{
8058c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	/* Some Broadcom based Bluetooth controllers do not support the
8088c2ecf20Sopenharmony_ci	 * Delete Stored Link Key command. They are clearly indicating its
8098c2ecf20Sopenharmony_ci	 * absence in the bit mask of supported commands.
8108c2ecf20Sopenharmony_ci	 *
8118c2ecf20Sopenharmony_ci	 * Check the supported commands and only if the command is marked
8128c2ecf20Sopenharmony_ci	 * as supported send it. If not supported assume that the controller
8138c2ecf20Sopenharmony_ci	 * does not have actual support for stored link keys which makes this
8148c2ecf20Sopenharmony_ci	 * command redundant anyway.
8158c2ecf20Sopenharmony_ci	 *
8168c2ecf20Sopenharmony_ci	 * Some controllers indicate that they support handling deleting
8178c2ecf20Sopenharmony_ci	 * stored link keys, but they don't. The quirk lets a driver
8188c2ecf20Sopenharmony_ci	 * just disable this command.
8198c2ecf20Sopenharmony_ci	 */
8208c2ecf20Sopenharmony_ci	if (hdev->commands[6] & 0x80 &&
8218c2ecf20Sopenharmony_ci	    !test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) {
8228c2ecf20Sopenharmony_ci		struct hci_cp_delete_stored_link_key cp;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci		bacpy(&cp.bdaddr, BDADDR_ANY);
8258c2ecf20Sopenharmony_ci		cp.delete_all = 0x01;
8268c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY,
8278c2ecf20Sopenharmony_ci			    sizeof(cp), &cp);
8288c2ecf20Sopenharmony_ci	}
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	/* Set event mask page 2 if the HCI command for it is supported */
8318c2ecf20Sopenharmony_ci	if (hdev->commands[22] & 0x04)
8328c2ecf20Sopenharmony_ci		hci_set_event_mask_page_2(req);
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	/* Read local codec list if the HCI command is supported */
8358c2ecf20Sopenharmony_ci	if (hdev->commands[29] & 0x20)
8368c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_LOCAL_CODECS, 0, NULL);
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	/* Read local pairing options if the HCI command is supported */
8398c2ecf20Sopenharmony_ci	if (hdev->commands[41] & 0x08)
8408c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_LOCAL_PAIRING_OPTS, 0, NULL);
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	/* Get MWS transport configuration if the HCI command is supported */
8438c2ecf20Sopenharmony_ci	if (hdev->commands[30] & 0x08)
8448c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_GET_MWS_TRANSPORT_CONFIG, 0, NULL);
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	/* Check for Synchronization Train support */
8478c2ecf20Sopenharmony_ci	if (lmp_sync_train_capable(hdev))
8488c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	/* Enable Secure Connections if supported and configured */
8518c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
8528c2ecf20Sopenharmony_ci	    bredr_sc_enabled(hdev)) {
8538c2ecf20Sopenharmony_ci		u8 support = 0x01;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT,
8568c2ecf20Sopenharmony_ci			    sizeof(support), &support);
8578c2ecf20Sopenharmony_ci	}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	/* Set erroneous data reporting if supported to the wideband speech
8608c2ecf20Sopenharmony_ci	 * setting value
8618c2ecf20Sopenharmony_ci	 */
8628c2ecf20Sopenharmony_ci	if (hdev->commands[18] & 0x08 &&
8638c2ecf20Sopenharmony_ci	    !test_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks)) {
8648c2ecf20Sopenharmony_ci		bool enabled = hci_dev_test_flag(hdev,
8658c2ecf20Sopenharmony_ci						 HCI_WIDEBAND_SPEECH_ENABLED);
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci		if (enabled !=
8688c2ecf20Sopenharmony_ci		    (hdev->err_data_reporting == ERR_DATA_REPORTING_ENABLED)) {
8698c2ecf20Sopenharmony_ci			struct hci_cp_write_def_err_data_reporting cp;
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci			cp.err_data_reporting = enabled ?
8728c2ecf20Sopenharmony_ci						ERR_DATA_REPORTING_ENABLED :
8738c2ecf20Sopenharmony_ci						ERR_DATA_REPORTING_DISABLED;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci			hci_req_add(req, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING,
8768c2ecf20Sopenharmony_ci				    sizeof(cp), &cp);
8778c2ecf20Sopenharmony_ci		}
8788c2ecf20Sopenharmony_ci	}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	/* Set Suggested Default Data Length to maximum if supported */
8818c2ecf20Sopenharmony_ci	if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) {
8828c2ecf20Sopenharmony_ci		struct hci_cp_le_write_def_data_len cp;
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_ci		cp.tx_len = cpu_to_le16(hdev->le_max_tx_len);
8858c2ecf20Sopenharmony_ci		cp.tx_time = cpu_to_le16(hdev->le_max_tx_time);
8868c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_LE_WRITE_DEF_DATA_LEN, sizeof(cp), &cp);
8878c2ecf20Sopenharmony_ci	}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	/* Set Default PHY parameters if command is supported */
8908c2ecf20Sopenharmony_ci	if (hdev->commands[35] & 0x20) {
8918c2ecf20Sopenharmony_ci		struct hci_cp_le_set_default_phy cp;
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci		cp.all_phys = 0x00;
8948c2ecf20Sopenharmony_ci		cp.tx_phys = hdev->le_tx_def_phys;
8958c2ecf20Sopenharmony_ci		cp.rx_phys = hdev->le_rx_def_phys;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(cp), &cp);
8988c2ecf20Sopenharmony_ci	}
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	return 0;
9018c2ecf20Sopenharmony_ci}
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_cistatic int __hci_init(struct hci_dev *hdev)
9048c2ecf20Sopenharmony_ci{
9058c2ecf20Sopenharmony_ci	int err;
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT, NULL);
9088c2ecf20Sopenharmony_ci	if (err < 0)
9098c2ecf20Sopenharmony_ci		return err;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_SETUP))
9128c2ecf20Sopenharmony_ci		hci_debugfs_create_basic(hdev);
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT, NULL);
9158c2ecf20Sopenharmony_ci	if (err < 0)
9168c2ecf20Sopenharmony_ci		return err;
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	/* HCI_PRIMARY covers both single-mode LE, BR/EDR and dual-mode
9198c2ecf20Sopenharmony_ci	 * BR/EDR/LE type controllers. AMP controllers only need the
9208c2ecf20Sopenharmony_ci	 * first two stages of init.
9218c2ecf20Sopenharmony_ci	 */
9228c2ecf20Sopenharmony_ci	if (hdev->dev_type != HCI_PRIMARY)
9238c2ecf20Sopenharmony_ci		return 0;
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT, NULL);
9268c2ecf20Sopenharmony_ci	if (err < 0)
9278c2ecf20Sopenharmony_ci		return err;
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	err = __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT, NULL);
9308c2ecf20Sopenharmony_ci	if (err < 0)
9318c2ecf20Sopenharmony_ci		return err;
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	/* This function is only called when the controller is actually in
9348c2ecf20Sopenharmony_ci	 * configured state. When the controller is marked as unconfigured,
9358c2ecf20Sopenharmony_ci	 * this initialization procedure is not run.
9368c2ecf20Sopenharmony_ci	 *
9378c2ecf20Sopenharmony_ci	 * It means that it is possible that a controller runs through its
9388c2ecf20Sopenharmony_ci	 * setup phase and then discovers missing settings. If that is the
9398c2ecf20Sopenharmony_ci	 * case, then this function will not be called. It then will only
9408c2ecf20Sopenharmony_ci	 * be called during the config phase.
9418c2ecf20Sopenharmony_ci	 *
9428c2ecf20Sopenharmony_ci	 * So only when in setup phase or config phase, create the debugfs
9438c2ecf20Sopenharmony_ci	 * entries and register the SMP channels.
9448c2ecf20Sopenharmony_ci	 */
9458c2ecf20Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
9468c2ecf20Sopenharmony_ci	    !hci_dev_test_flag(hdev, HCI_CONFIG))
9478c2ecf20Sopenharmony_ci		return 0;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	hci_debugfs_create_common(hdev);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	if (lmp_bredr_capable(hdev))
9528c2ecf20Sopenharmony_ci		hci_debugfs_create_bredr(hdev);
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	if (lmp_le_capable(hdev))
9558c2ecf20Sopenharmony_ci		hci_debugfs_create_le(hdev);
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci	return 0;
9588c2ecf20Sopenharmony_ci}
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_cistatic int hci_init0_req(struct hci_request *req, unsigned long opt)
9618c2ecf20Sopenharmony_ci{
9628c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	BT_DBG("%s %ld", hdev->name, opt);
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	/* Reset */
9678c2ecf20Sopenharmony_ci	if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks))
9688c2ecf20Sopenharmony_ci		hci_reset_req(req, 0);
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	/* Read Local Version */
9718c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	/* Read BD Address */
9748c2ecf20Sopenharmony_ci	if (hdev->set_bdaddr)
9758c2ecf20Sopenharmony_ci		hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL);
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci	return 0;
9788c2ecf20Sopenharmony_ci}
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_cistatic int __hci_unconf_init(struct hci_dev *hdev)
9818c2ecf20Sopenharmony_ci{
9828c2ecf20Sopenharmony_ci	int err;
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
9858c2ecf20Sopenharmony_ci		return 0;
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	err = __hci_req_sync(hdev, hci_init0_req, 0, HCI_INIT_TIMEOUT, NULL);
9888c2ecf20Sopenharmony_ci	if (err < 0)
9898c2ecf20Sopenharmony_ci		return err;
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_SETUP))
9928c2ecf20Sopenharmony_ci		hci_debugfs_create_basic(hdev);
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	return 0;
9958c2ecf20Sopenharmony_ci}
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_cistatic int hci_scan_req(struct hci_request *req, unsigned long opt)
9988c2ecf20Sopenharmony_ci{
9998c2ecf20Sopenharmony_ci	__u8 scan = opt;
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	BT_DBG("%s %x", req->hdev->name, scan);
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	/* Inquiry and Page scans */
10048c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
10058c2ecf20Sopenharmony_ci	return 0;
10068c2ecf20Sopenharmony_ci}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_cistatic int hci_auth_req(struct hci_request *req, unsigned long opt)
10098c2ecf20Sopenharmony_ci{
10108c2ecf20Sopenharmony_ci	__u8 auth = opt;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	BT_DBG("%s %x", req->hdev->name, auth);
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	/* Authentication */
10158c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth);
10168c2ecf20Sopenharmony_ci	return 0;
10178c2ecf20Sopenharmony_ci}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_cistatic int hci_encrypt_req(struct hci_request *req, unsigned long opt)
10208c2ecf20Sopenharmony_ci{
10218c2ecf20Sopenharmony_ci	__u8 encrypt = opt;
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	BT_DBG("%s %x", req->hdev->name, encrypt);
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	/* Encryption */
10268c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt);
10278c2ecf20Sopenharmony_ci	return 0;
10288c2ecf20Sopenharmony_ci}
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_cistatic int hci_linkpol_req(struct hci_request *req, unsigned long opt)
10318c2ecf20Sopenharmony_ci{
10328c2ecf20Sopenharmony_ci	__le16 policy = cpu_to_le16(opt);
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	BT_DBG("%s %x", req->hdev->name, policy);
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci	/* Default link policy */
10378c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy);
10388c2ecf20Sopenharmony_ci	return 0;
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci/* Get HCI device by index.
10428c2ecf20Sopenharmony_ci * Device is held on return. */
10438c2ecf20Sopenharmony_cistruct hci_dev *hci_dev_get(int index)
10448c2ecf20Sopenharmony_ci{
10458c2ecf20Sopenharmony_ci	struct hci_dev *hdev = NULL, *d;
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	BT_DBG("%d", index);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	if (index < 0)
10508c2ecf20Sopenharmony_ci		return NULL;
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	read_lock(&hci_dev_list_lock);
10538c2ecf20Sopenharmony_ci	list_for_each_entry(d, &hci_dev_list, list) {
10548c2ecf20Sopenharmony_ci		if (d->id == index) {
10558c2ecf20Sopenharmony_ci			hdev = hci_dev_hold(d);
10568c2ecf20Sopenharmony_ci			break;
10578c2ecf20Sopenharmony_ci		}
10588c2ecf20Sopenharmony_ci	}
10598c2ecf20Sopenharmony_ci	read_unlock(&hci_dev_list_lock);
10608c2ecf20Sopenharmony_ci	return hdev;
10618c2ecf20Sopenharmony_ci}
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci/* ---- Inquiry support ---- */
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_cibool hci_discovery_active(struct hci_dev *hdev)
10668c2ecf20Sopenharmony_ci{
10678c2ecf20Sopenharmony_ci	struct discovery_state *discov = &hdev->discovery;
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	switch (discov->state) {
10708c2ecf20Sopenharmony_ci	case DISCOVERY_FINDING:
10718c2ecf20Sopenharmony_ci	case DISCOVERY_RESOLVING:
10728c2ecf20Sopenharmony_ci		return true;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	default:
10758c2ecf20Sopenharmony_ci		return false;
10768c2ecf20Sopenharmony_ci	}
10778c2ecf20Sopenharmony_ci}
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_civoid hci_discovery_set_state(struct hci_dev *hdev, int state)
10808c2ecf20Sopenharmony_ci{
10818c2ecf20Sopenharmony_ci	int old_state = hdev->discovery.state;
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	BT_DBG("%s state %u -> %u", hdev->name, hdev->discovery.state, state);
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	if (old_state == state)
10868c2ecf20Sopenharmony_ci		return;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	hdev->discovery.state = state;
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	switch (state) {
10918c2ecf20Sopenharmony_ci	case DISCOVERY_STOPPED:
10928c2ecf20Sopenharmony_ci		hci_update_background_scan(hdev);
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci		if (old_state != DISCOVERY_STARTING)
10958c2ecf20Sopenharmony_ci			mgmt_discovering(hdev, 0);
10968c2ecf20Sopenharmony_ci		break;
10978c2ecf20Sopenharmony_ci	case DISCOVERY_STARTING:
10988c2ecf20Sopenharmony_ci		break;
10998c2ecf20Sopenharmony_ci	case DISCOVERY_FINDING:
11008c2ecf20Sopenharmony_ci		mgmt_discovering(hdev, 1);
11018c2ecf20Sopenharmony_ci		break;
11028c2ecf20Sopenharmony_ci	case DISCOVERY_RESOLVING:
11038c2ecf20Sopenharmony_ci		break;
11048c2ecf20Sopenharmony_ci	case DISCOVERY_STOPPING:
11058c2ecf20Sopenharmony_ci		break;
11068c2ecf20Sopenharmony_ci	}
11078c2ecf20Sopenharmony_ci}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_civoid hci_inquiry_cache_flush(struct hci_dev *hdev)
11108c2ecf20Sopenharmony_ci{
11118c2ecf20Sopenharmony_ci	struct discovery_state *cache = &hdev->discovery;
11128c2ecf20Sopenharmony_ci	struct inquiry_entry *p, *n;
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	list_for_each_entry_safe(p, n, &cache->all, all) {
11158c2ecf20Sopenharmony_ci		list_del(&p->all);
11168c2ecf20Sopenharmony_ci		kfree(p);
11178c2ecf20Sopenharmony_ci	}
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&cache->unknown);
11208c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&cache->resolve);
11218c2ecf20Sopenharmony_ci}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_cistruct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
11248c2ecf20Sopenharmony_ci					       bdaddr_t *bdaddr)
11258c2ecf20Sopenharmony_ci{
11268c2ecf20Sopenharmony_ci	struct discovery_state *cache = &hdev->discovery;
11278c2ecf20Sopenharmony_ci	struct inquiry_entry *e;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	BT_DBG("cache %p, %pMR", cache, bdaddr);
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	list_for_each_entry(e, &cache->all, all) {
11328c2ecf20Sopenharmony_ci		if (!bacmp(&e->data.bdaddr, bdaddr))
11338c2ecf20Sopenharmony_ci			return e;
11348c2ecf20Sopenharmony_ci	}
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	return NULL;
11378c2ecf20Sopenharmony_ci}
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_cistruct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
11408c2ecf20Sopenharmony_ci						       bdaddr_t *bdaddr)
11418c2ecf20Sopenharmony_ci{
11428c2ecf20Sopenharmony_ci	struct discovery_state *cache = &hdev->discovery;
11438c2ecf20Sopenharmony_ci	struct inquiry_entry *e;
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	BT_DBG("cache %p, %pMR", cache, bdaddr);
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci	list_for_each_entry(e, &cache->unknown, list) {
11488c2ecf20Sopenharmony_ci		if (!bacmp(&e->data.bdaddr, bdaddr))
11498c2ecf20Sopenharmony_ci			return e;
11508c2ecf20Sopenharmony_ci	}
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ci	return NULL;
11538c2ecf20Sopenharmony_ci}
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_cistruct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
11568c2ecf20Sopenharmony_ci						       bdaddr_t *bdaddr,
11578c2ecf20Sopenharmony_ci						       int state)
11588c2ecf20Sopenharmony_ci{
11598c2ecf20Sopenharmony_ci	struct discovery_state *cache = &hdev->discovery;
11608c2ecf20Sopenharmony_ci	struct inquiry_entry *e;
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state);
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	list_for_each_entry(e, &cache->resolve, list) {
11658c2ecf20Sopenharmony_ci		if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state)
11668c2ecf20Sopenharmony_ci			return e;
11678c2ecf20Sopenharmony_ci		if (!bacmp(&e->data.bdaddr, bdaddr))
11688c2ecf20Sopenharmony_ci			return e;
11698c2ecf20Sopenharmony_ci	}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	return NULL;
11728c2ecf20Sopenharmony_ci}
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_civoid hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
11758c2ecf20Sopenharmony_ci				      struct inquiry_entry *ie)
11768c2ecf20Sopenharmony_ci{
11778c2ecf20Sopenharmony_ci	struct discovery_state *cache = &hdev->discovery;
11788c2ecf20Sopenharmony_ci	struct list_head *pos = &cache->resolve;
11798c2ecf20Sopenharmony_ci	struct inquiry_entry *p;
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ci	list_del(&ie->list);
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	list_for_each_entry(p, &cache->resolve, list) {
11848c2ecf20Sopenharmony_ci		if (p->name_state != NAME_PENDING &&
11858c2ecf20Sopenharmony_ci		    abs(p->data.rssi) >= abs(ie->data.rssi))
11868c2ecf20Sopenharmony_ci			break;
11878c2ecf20Sopenharmony_ci		pos = &p->list;
11888c2ecf20Sopenharmony_ci	}
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	list_add(&ie->list, pos);
11918c2ecf20Sopenharmony_ci}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ciu32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
11948c2ecf20Sopenharmony_ci			     bool name_known)
11958c2ecf20Sopenharmony_ci{
11968c2ecf20Sopenharmony_ci	struct discovery_state *cache = &hdev->discovery;
11978c2ecf20Sopenharmony_ci	struct inquiry_entry *ie;
11988c2ecf20Sopenharmony_ci	u32 flags = 0;
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	BT_DBG("cache %p, %pMR", cache, &data->bdaddr);
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	hci_remove_remote_oob_data(hdev, &data->bdaddr, BDADDR_BREDR);
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	if (!data->ssp_mode)
12058c2ecf20Sopenharmony_ci		flags |= MGMT_DEV_FOUND_LEGACY_PAIRING;
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr);
12088c2ecf20Sopenharmony_ci	if (ie) {
12098c2ecf20Sopenharmony_ci		if (!ie->data.ssp_mode)
12108c2ecf20Sopenharmony_ci			flags |= MGMT_DEV_FOUND_LEGACY_PAIRING;
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci		if (ie->name_state == NAME_NEEDED &&
12138c2ecf20Sopenharmony_ci		    data->rssi != ie->data.rssi) {
12148c2ecf20Sopenharmony_ci			ie->data.rssi = data->rssi;
12158c2ecf20Sopenharmony_ci			hci_inquiry_cache_update_resolve(hdev, ie);
12168c2ecf20Sopenharmony_ci		}
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci		goto update;
12198c2ecf20Sopenharmony_ci	}
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	/* Entry not in the cache. Add new one. */
12228c2ecf20Sopenharmony_ci	ie = kzalloc(sizeof(*ie), GFP_KERNEL);
12238c2ecf20Sopenharmony_ci	if (!ie) {
12248c2ecf20Sopenharmony_ci		flags |= MGMT_DEV_FOUND_CONFIRM_NAME;
12258c2ecf20Sopenharmony_ci		goto done;
12268c2ecf20Sopenharmony_ci	}
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	list_add(&ie->all, &cache->all);
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	if (name_known) {
12318c2ecf20Sopenharmony_ci		ie->name_state = NAME_KNOWN;
12328c2ecf20Sopenharmony_ci	} else {
12338c2ecf20Sopenharmony_ci		ie->name_state = NAME_NOT_KNOWN;
12348c2ecf20Sopenharmony_ci		list_add(&ie->list, &cache->unknown);
12358c2ecf20Sopenharmony_ci	}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ciupdate:
12388c2ecf20Sopenharmony_ci	if (name_known && ie->name_state != NAME_KNOWN &&
12398c2ecf20Sopenharmony_ci	    ie->name_state != NAME_PENDING) {
12408c2ecf20Sopenharmony_ci		ie->name_state = NAME_KNOWN;
12418c2ecf20Sopenharmony_ci		list_del(&ie->list);
12428c2ecf20Sopenharmony_ci	}
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	memcpy(&ie->data, data, sizeof(*data));
12458c2ecf20Sopenharmony_ci	ie->timestamp = jiffies;
12468c2ecf20Sopenharmony_ci	cache->timestamp = jiffies;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	if (ie->name_state == NAME_NOT_KNOWN)
12498c2ecf20Sopenharmony_ci		flags |= MGMT_DEV_FOUND_CONFIRM_NAME;
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_cidone:
12528c2ecf20Sopenharmony_ci	return flags;
12538c2ecf20Sopenharmony_ci}
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_cistatic int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf)
12568c2ecf20Sopenharmony_ci{
12578c2ecf20Sopenharmony_ci	struct discovery_state *cache = &hdev->discovery;
12588c2ecf20Sopenharmony_ci	struct inquiry_info *info = (struct inquiry_info *) buf;
12598c2ecf20Sopenharmony_ci	struct inquiry_entry *e;
12608c2ecf20Sopenharmony_ci	int copied = 0;
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	list_for_each_entry(e, &cache->all, all) {
12638c2ecf20Sopenharmony_ci		struct inquiry_data *data = &e->data;
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci		if (copied >= num)
12668c2ecf20Sopenharmony_ci			break;
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci		bacpy(&info->bdaddr, &data->bdaddr);
12698c2ecf20Sopenharmony_ci		info->pscan_rep_mode	= data->pscan_rep_mode;
12708c2ecf20Sopenharmony_ci		info->pscan_period_mode	= data->pscan_period_mode;
12718c2ecf20Sopenharmony_ci		info->pscan_mode	= data->pscan_mode;
12728c2ecf20Sopenharmony_ci		memcpy(info->dev_class, data->dev_class, 3);
12738c2ecf20Sopenharmony_ci		info->clock_offset	= data->clock_offset;
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci		info++;
12768c2ecf20Sopenharmony_ci		copied++;
12778c2ecf20Sopenharmony_ci	}
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci	BT_DBG("cache %p, copied %d", cache, copied);
12808c2ecf20Sopenharmony_ci	return copied;
12818c2ecf20Sopenharmony_ci}
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_cistatic int hci_inq_req(struct hci_request *req, unsigned long opt)
12848c2ecf20Sopenharmony_ci{
12858c2ecf20Sopenharmony_ci	struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt;
12868c2ecf20Sopenharmony_ci	struct hci_dev *hdev = req->hdev;
12878c2ecf20Sopenharmony_ci	struct hci_cp_inquiry cp;
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci	if (test_bit(HCI_INQUIRY, &hdev->flags))
12928c2ecf20Sopenharmony_ci		return 0;
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	/* Start Inquiry */
12958c2ecf20Sopenharmony_ci	memcpy(&cp.lap, &ir->lap, 3);
12968c2ecf20Sopenharmony_ci	cp.length  = ir->length;
12978c2ecf20Sopenharmony_ci	cp.num_rsp = ir->num_rsp;
12988c2ecf20Sopenharmony_ci	hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	return 0;
13018c2ecf20Sopenharmony_ci}
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ciint hci_inquiry(void __user *arg)
13048c2ecf20Sopenharmony_ci{
13058c2ecf20Sopenharmony_ci	__u8 __user *ptr = arg;
13068c2ecf20Sopenharmony_ci	struct hci_inquiry_req ir;
13078c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
13088c2ecf20Sopenharmony_ci	int err = 0, do_inquiry = 0, max_rsp;
13098c2ecf20Sopenharmony_ci	long timeo;
13108c2ecf20Sopenharmony_ci	__u8 *buf;
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	if (copy_from_user(&ir, ptr, sizeof(ir)))
13138c2ecf20Sopenharmony_ci		return -EFAULT;
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	hdev = hci_dev_get(ir.dev_id);
13168c2ecf20Sopenharmony_ci	if (!hdev)
13178c2ecf20Sopenharmony_ci		return -ENODEV;
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
13208c2ecf20Sopenharmony_ci		err = -EBUSY;
13218c2ecf20Sopenharmony_ci		goto done;
13228c2ecf20Sopenharmony_ci	}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
13258c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
13268c2ecf20Sopenharmony_ci		goto done;
13278c2ecf20Sopenharmony_ci	}
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	if (hdev->dev_type != HCI_PRIMARY) {
13308c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
13318c2ecf20Sopenharmony_ci		goto done;
13328c2ecf20Sopenharmony_ci	}
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
13358c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
13368c2ecf20Sopenharmony_ci		goto done;
13378c2ecf20Sopenharmony_ci	}
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	/* Restrict maximum inquiry length to 60 seconds */
13408c2ecf20Sopenharmony_ci	if (ir.length > 60) {
13418c2ecf20Sopenharmony_ci		err = -EINVAL;
13428c2ecf20Sopenharmony_ci		goto done;
13438c2ecf20Sopenharmony_ci	}
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
13468c2ecf20Sopenharmony_ci	if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
13478c2ecf20Sopenharmony_ci	    inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) {
13488c2ecf20Sopenharmony_ci		hci_inquiry_cache_flush(hdev);
13498c2ecf20Sopenharmony_ci		do_inquiry = 1;
13508c2ecf20Sopenharmony_ci	}
13518c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	timeo = ir.length * msecs_to_jiffies(2000);
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	if (do_inquiry) {
13568c2ecf20Sopenharmony_ci		err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir,
13578c2ecf20Sopenharmony_ci				   timeo, NULL);
13588c2ecf20Sopenharmony_ci		if (err < 0)
13598c2ecf20Sopenharmony_ci			goto done;
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci		/* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is
13628c2ecf20Sopenharmony_ci		 * cleared). If it is interrupted by a signal, return -EINTR.
13638c2ecf20Sopenharmony_ci		 */
13648c2ecf20Sopenharmony_ci		if (wait_on_bit(&hdev->flags, HCI_INQUIRY,
13658c2ecf20Sopenharmony_ci				TASK_INTERRUPTIBLE)) {
13668c2ecf20Sopenharmony_ci			err = -EINTR;
13678c2ecf20Sopenharmony_ci			goto done;
13688c2ecf20Sopenharmony_ci		}
13698c2ecf20Sopenharmony_ci	}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	/* for unlimited number of responses we will use buffer with
13728c2ecf20Sopenharmony_ci	 * 255 entries
13738c2ecf20Sopenharmony_ci	 */
13748c2ecf20Sopenharmony_ci	max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	/* cache_dump can't sleep. Therefore we allocate temp buffer and then
13778c2ecf20Sopenharmony_ci	 * copy it to the user space.
13788c2ecf20Sopenharmony_ci	 */
13798c2ecf20Sopenharmony_ci	buf = kmalloc_array(max_rsp, sizeof(struct inquiry_info), GFP_KERNEL);
13808c2ecf20Sopenharmony_ci	if (!buf) {
13818c2ecf20Sopenharmony_ci		err = -ENOMEM;
13828c2ecf20Sopenharmony_ci		goto done;
13838c2ecf20Sopenharmony_ci	}
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
13868c2ecf20Sopenharmony_ci	ir.num_rsp = inquiry_cache_dump(hdev, max_rsp, buf);
13878c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	BT_DBG("num_rsp %d", ir.num_rsp);
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	if (!copy_to_user(ptr, &ir, sizeof(ir))) {
13928c2ecf20Sopenharmony_ci		ptr += sizeof(ir);
13938c2ecf20Sopenharmony_ci		if (copy_to_user(ptr, buf, sizeof(struct inquiry_info) *
13948c2ecf20Sopenharmony_ci				 ir.num_rsp))
13958c2ecf20Sopenharmony_ci			err = -EFAULT;
13968c2ecf20Sopenharmony_ci	} else
13978c2ecf20Sopenharmony_ci		err = -EFAULT;
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	kfree(buf);
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_cidone:
14028c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
14038c2ecf20Sopenharmony_ci	return err;
14048c2ecf20Sopenharmony_ci}
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_ci/**
14078c2ecf20Sopenharmony_ci * hci_dev_get_bd_addr_from_property - Get the Bluetooth Device Address
14088c2ecf20Sopenharmony_ci *				       (BD_ADDR) for a HCI device from
14098c2ecf20Sopenharmony_ci *				       a firmware node property.
14108c2ecf20Sopenharmony_ci * @hdev:	The HCI device
14118c2ecf20Sopenharmony_ci *
14128c2ecf20Sopenharmony_ci * Search the firmware node for 'local-bd-address'.
14138c2ecf20Sopenharmony_ci *
14148c2ecf20Sopenharmony_ci * All-zero BD addresses are rejected, because those could be properties
14158c2ecf20Sopenharmony_ci * that exist in the firmware tables, but were not updated by the firmware. For
14168c2ecf20Sopenharmony_ci * example, the DTS could define 'local-bd-address', with zero BD addresses.
14178c2ecf20Sopenharmony_ci */
14188c2ecf20Sopenharmony_cistatic void hci_dev_get_bd_addr_from_property(struct hci_dev *hdev)
14198c2ecf20Sopenharmony_ci{
14208c2ecf20Sopenharmony_ci	struct fwnode_handle *fwnode = dev_fwnode(hdev->dev.parent);
14218c2ecf20Sopenharmony_ci	bdaddr_t ba;
14228c2ecf20Sopenharmony_ci	int ret;
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ci	ret = fwnode_property_read_u8_array(fwnode, "local-bd-address",
14258c2ecf20Sopenharmony_ci					    (u8 *)&ba, sizeof(ba));
14268c2ecf20Sopenharmony_ci	if (ret < 0 || !bacmp(&ba, BDADDR_ANY))
14278c2ecf20Sopenharmony_ci		return;
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci	bacpy(&hdev->public_addr, &ba);
14308c2ecf20Sopenharmony_ci}
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_cistatic int hci_dev_do_open(struct hci_dev *hdev)
14338c2ecf20Sopenharmony_ci{
14348c2ecf20Sopenharmony_ci	int ret = 0;
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci	BT_DBG("%s %p", hdev->name, hdev);
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	hci_req_sync_lock(hdev);
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
14418c2ecf20Sopenharmony_ci		ret = -ENODEV;
14428c2ecf20Sopenharmony_ci		goto done;
14438c2ecf20Sopenharmony_ci	}
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
14468c2ecf20Sopenharmony_ci	    !hci_dev_test_flag(hdev, HCI_CONFIG)) {
14478c2ecf20Sopenharmony_ci		/* Check for rfkill but allow the HCI setup stage to
14488c2ecf20Sopenharmony_ci		 * proceed (which in itself doesn't cause any RF activity).
14498c2ecf20Sopenharmony_ci		 */
14508c2ecf20Sopenharmony_ci		if (hci_dev_test_flag(hdev, HCI_RFKILLED)) {
14518c2ecf20Sopenharmony_ci			ret = -ERFKILL;
14528c2ecf20Sopenharmony_ci			goto done;
14538c2ecf20Sopenharmony_ci		}
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci		/* Check for valid public address or a configured static
14568c2ecf20Sopenharmony_ci		 * random adddress, but let the HCI setup proceed to
14578c2ecf20Sopenharmony_ci		 * be able to determine if there is a public address
14588c2ecf20Sopenharmony_ci		 * or not.
14598c2ecf20Sopenharmony_ci		 *
14608c2ecf20Sopenharmony_ci		 * In case of user channel usage, it is not important
14618c2ecf20Sopenharmony_ci		 * if a public address or static random address is
14628c2ecf20Sopenharmony_ci		 * available.
14638c2ecf20Sopenharmony_ci		 *
14648c2ecf20Sopenharmony_ci		 * This check is only valid for BR/EDR controllers
14658c2ecf20Sopenharmony_ci		 * since AMP controllers do not have an address.
14668c2ecf20Sopenharmony_ci		 */
14678c2ecf20Sopenharmony_ci		if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
14688c2ecf20Sopenharmony_ci		    hdev->dev_type == HCI_PRIMARY &&
14698c2ecf20Sopenharmony_ci		    !bacmp(&hdev->bdaddr, BDADDR_ANY) &&
14708c2ecf20Sopenharmony_ci		    !bacmp(&hdev->static_addr, BDADDR_ANY)) {
14718c2ecf20Sopenharmony_ci			ret = -EADDRNOTAVAIL;
14728c2ecf20Sopenharmony_ci			goto done;
14738c2ecf20Sopenharmony_ci		}
14748c2ecf20Sopenharmony_ci	}
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_ci	if (test_bit(HCI_UP, &hdev->flags)) {
14778c2ecf20Sopenharmony_ci		ret = -EALREADY;
14788c2ecf20Sopenharmony_ci		goto done;
14798c2ecf20Sopenharmony_ci	}
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ci	if (hdev->open(hdev)) {
14828c2ecf20Sopenharmony_ci		ret = -EIO;
14838c2ecf20Sopenharmony_ci		goto done;
14848c2ecf20Sopenharmony_ci	}
14858c2ecf20Sopenharmony_ci
14868c2ecf20Sopenharmony_ci	set_bit(HCI_RUNNING, &hdev->flags);
14878c2ecf20Sopenharmony_ci	hci_sock_dev_event(hdev, HCI_DEV_OPEN);
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci	atomic_set(&hdev->cmd_cnt, 1);
14908c2ecf20Sopenharmony_ci	set_bit(HCI_INIT, &hdev->flags);
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
14938c2ecf20Sopenharmony_ci	    test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) {
14948c2ecf20Sopenharmony_ci		bool invalid_bdaddr;
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci		hci_sock_dev_event(hdev, HCI_DEV_SETUP);
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci		if (hdev->setup)
14998c2ecf20Sopenharmony_ci			ret = hdev->setup(hdev);
15008c2ecf20Sopenharmony_ci
15018c2ecf20Sopenharmony_ci		/* The transport driver can set the quirk to mark the
15028c2ecf20Sopenharmony_ci		 * BD_ADDR invalid before creating the HCI device or in
15038c2ecf20Sopenharmony_ci		 * its setup callback.
15048c2ecf20Sopenharmony_ci		 */
15058c2ecf20Sopenharmony_ci		invalid_bdaddr = test_bit(HCI_QUIRK_INVALID_BDADDR,
15068c2ecf20Sopenharmony_ci					  &hdev->quirks);
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci		if (ret)
15098c2ecf20Sopenharmony_ci			goto setup_failed;
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci		if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) {
15128c2ecf20Sopenharmony_ci			if (!bacmp(&hdev->public_addr, BDADDR_ANY))
15138c2ecf20Sopenharmony_ci				hci_dev_get_bd_addr_from_property(hdev);
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_ci			if (bacmp(&hdev->public_addr, BDADDR_ANY) &&
15168c2ecf20Sopenharmony_ci			    hdev->set_bdaddr) {
15178c2ecf20Sopenharmony_ci				ret = hdev->set_bdaddr(hdev,
15188c2ecf20Sopenharmony_ci						       &hdev->public_addr);
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci				/* If setting of the BD_ADDR from the device
15218c2ecf20Sopenharmony_ci				 * property succeeds, then treat the address
15228c2ecf20Sopenharmony_ci				 * as valid even if the invalid BD_ADDR
15238c2ecf20Sopenharmony_ci				 * quirk indicates otherwise.
15248c2ecf20Sopenharmony_ci				 */
15258c2ecf20Sopenharmony_ci				if (!ret)
15268c2ecf20Sopenharmony_ci					invalid_bdaddr = false;
15278c2ecf20Sopenharmony_ci			}
15288c2ecf20Sopenharmony_ci		}
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_cisetup_failed:
15318c2ecf20Sopenharmony_ci		/* The transport driver can set these quirks before
15328c2ecf20Sopenharmony_ci		 * creating the HCI device or in its setup callback.
15338c2ecf20Sopenharmony_ci		 *
15348c2ecf20Sopenharmony_ci		 * For the invalid BD_ADDR quirk it is possible that
15358c2ecf20Sopenharmony_ci		 * it becomes a valid address if the bootloader does
15368c2ecf20Sopenharmony_ci		 * provide it (see above).
15378c2ecf20Sopenharmony_ci		 *
15388c2ecf20Sopenharmony_ci		 * In case any of them is set, the controller has to
15398c2ecf20Sopenharmony_ci		 * start up as unconfigured.
15408c2ecf20Sopenharmony_ci		 */
15418c2ecf20Sopenharmony_ci		if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
15428c2ecf20Sopenharmony_ci		    invalid_bdaddr)
15438c2ecf20Sopenharmony_ci			hci_dev_set_flag(hdev, HCI_UNCONFIGURED);
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_ci		/* For an unconfigured controller it is required to
15468c2ecf20Sopenharmony_ci		 * read at least the version information provided by
15478c2ecf20Sopenharmony_ci		 * the Read Local Version Information command.
15488c2ecf20Sopenharmony_ci		 *
15498c2ecf20Sopenharmony_ci		 * If the set_bdaddr driver callback is provided, then
15508c2ecf20Sopenharmony_ci		 * also the original Bluetooth public device address
15518c2ecf20Sopenharmony_ci		 * will be read using the Read BD Address command.
15528c2ecf20Sopenharmony_ci		 */
15538c2ecf20Sopenharmony_ci		if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
15548c2ecf20Sopenharmony_ci			ret = __hci_unconf_init(hdev);
15558c2ecf20Sopenharmony_ci	}
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_CONFIG)) {
15588c2ecf20Sopenharmony_ci		/* If public address change is configured, ensure that
15598c2ecf20Sopenharmony_ci		 * the address gets programmed. If the driver does not
15608c2ecf20Sopenharmony_ci		 * support changing the public address, fail the power
15618c2ecf20Sopenharmony_ci		 * on procedure.
15628c2ecf20Sopenharmony_ci		 */
15638c2ecf20Sopenharmony_ci		if (bacmp(&hdev->public_addr, BDADDR_ANY) &&
15648c2ecf20Sopenharmony_ci		    hdev->set_bdaddr)
15658c2ecf20Sopenharmony_ci			ret = hdev->set_bdaddr(hdev, &hdev->public_addr);
15668c2ecf20Sopenharmony_ci		else
15678c2ecf20Sopenharmony_ci			ret = -EADDRNOTAVAIL;
15688c2ecf20Sopenharmony_ci	}
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	if (!ret) {
15718c2ecf20Sopenharmony_ci		if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
15728c2ecf20Sopenharmony_ci		    !hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
15738c2ecf20Sopenharmony_ci			ret = __hci_init(hdev);
15748c2ecf20Sopenharmony_ci			if (!ret && hdev->post_init)
15758c2ecf20Sopenharmony_ci				ret = hdev->post_init(hdev);
15768c2ecf20Sopenharmony_ci		}
15778c2ecf20Sopenharmony_ci	}
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ci	/* If the HCI Reset command is clearing all diagnostic settings,
15808c2ecf20Sopenharmony_ci	 * then they need to be reprogrammed after the init procedure
15818c2ecf20Sopenharmony_ci	 * completed.
15828c2ecf20Sopenharmony_ci	 */
15838c2ecf20Sopenharmony_ci	if (test_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks) &&
15848c2ecf20Sopenharmony_ci	    !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
15858c2ecf20Sopenharmony_ci	    hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) && hdev->set_diag)
15868c2ecf20Sopenharmony_ci		ret = hdev->set_diag(hdev, true);
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	msft_do_open(hdev);
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	clear_bit(HCI_INIT, &hdev->flags);
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci	if (!ret) {
15938c2ecf20Sopenharmony_ci		hci_dev_hold(hdev);
15948c2ecf20Sopenharmony_ci		hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
15958c2ecf20Sopenharmony_ci		hci_adv_instances_set_rpa_expired(hdev, true);
15968c2ecf20Sopenharmony_ci		set_bit(HCI_UP, &hdev->flags);
15978c2ecf20Sopenharmony_ci		hci_sock_dev_event(hdev, HCI_DEV_UP);
15988c2ecf20Sopenharmony_ci		hci_leds_update_powered(hdev, true);
15998c2ecf20Sopenharmony_ci		if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
16008c2ecf20Sopenharmony_ci		    !hci_dev_test_flag(hdev, HCI_CONFIG) &&
16018c2ecf20Sopenharmony_ci		    !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
16028c2ecf20Sopenharmony_ci		    !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
16038c2ecf20Sopenharmony_ci		    hci_dev_test_flag(hdev, HCI_MGMT) &&
16048c2ecf20Sopenharmony_ci		    hdev->dev_type == HCI_PRIMARY) {
16058c2ecf20Sopenharmony_ci			ret = __hci_req_hci_power_on(hdev);
16068c2ecf20Sopenharmony_ci			mgmt_power_on(hdev, ret);
16078c2ecf20Sopenharmony_ci		}
16088c2ecf20Sopenharmony_ci	} else {
16098c2ecf20Sopenharmony_ci		/* Init failed, cleanup */
16108c2ecf20Sopenharmony_ci		flush_work(&hdev->tx_work);
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_ci		/* Since hci_rx_work() is possible to awake new cmd_work
16138c2ecf20Sopenharmony_ci		 * it should be flushed first to avoid unexpected call of
16148c2ecf20Sopenharmony_ci		 * hci_cmd_work()
16158c2ecf20Sopenharmony_ci		 */
16168c2ecf20Sopenharmony_ci		flush_work(&hdev->rx_work);
16178c2ecf20Sopenharmony_ci		flush_work(&hdev->cmd_work);
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci		skb_queue_purge(&hdev->cmd_q);
16208c2ecf20Sopenharmony_ci		skb_queue_purge(&hdev->rx_q);
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci		if (hdev->flush)
16238c2ecf20Sopenharmony_ci			hdev->flush(hdev);
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci		if (hdev->sent_cmd) {
16268c2ecf20Sopenharmony_ci			cancel_delayed_work_sync(&hdev->cmd_timer);
16278c2ecf20Sopenharmony_ci			kfree_skb(hdev->sent_cmd);
16288c2ecf20Sopenharmony_ci			hdev->sent_cmd = NULL;
16298c2ecf20Sopenharmony_ci		}
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci		clear_bit(HCI_RUNNING, &hdev->flags);
16328c2ecf20Sopenharmony_ci		hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci		hdev->close(hdev);
16358c2ecf20Sopenharmony_ci		hdev->flags &= BIT(HCI_RAW);
16368c2ecf20Sopenharmony_ci	}
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_cidone:
16398c2ecf20Sopenharmony_ci	hci_req_sync_unlock(hdev);
16408c2ecf20Sopenharmony_ci	return ret;
16418c2ecf20Sopenharmony_ci}
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci/* ---- HCI ioctl helpers ---- */
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ciint hci_dev_open(__u16 dev)
16468c2ecf20Sopenharmony_ci{
16478c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
16488c2ecf20Sopenharmony_ci	int err;
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	hdev = hci_dev_get(dev);
16518c2ecf20Sopenharmony_ci	if (!hdev)
16528c2ecf20Sopenharmony_ci		return -ENODEV;
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	/* Devices that are marked as unconfigured can only be powered
16558c2ecf20Sopenharmony_ci	 * up as user channel. Trying to bring them up as normal devices
16568c2ecf20Sopenharmony_ci	 * will result into a failure. Only user channel operation is
16578c2ecf20Sopenharmony_ci	 * possible.
16588c2ecf20Sopenharmony_ci	 *
16598c2ecf20Sopenharmony_ci	 * When this function is called for a user channel, the flag
16608c2ecf20Sopenharmony_ci	 * HCI_USER_CHANNEL will be set first before attempting to
16618c2ecf20Sopenharmony_ci	 * open the device.
16628c2ecf20Sopenharmony_ci	 */
16638c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
16648c2ecf20Sopenharmony_ci	    !hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
16658c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
16668c2ecf20Sopenharmony_ci		goto done;
16678c2ecf20Sopenharmony_ci	}
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	/* We need to ensure that no other power on/off work is pending
16708c2ecf20Sopenharmony_ci	 * before proceeding to call hci_dev_do_open. This is
16718c2ecf20Sopenharmony_ci	 * particularly important if the setup procedure has not yet
16728c2ecf20Sopenharmony_ci	 * completed.
16738c2ecf20Sopenharmony_ci	 */
16748c2ecf20Sopenharmony_ci	if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
16758c2ecf20Sopenharmony_ci		cancel_delayed_work(&hdev->power_off);
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci	/* After this call it is guaranteed that the setup procedure
16788c2ecf20Sopenharmony_ci	 * has finished. This means that error conditions like RFKILL
16798c2ecf20Sopenharmony_ci	 * or no valid public or static random address apply.
16808c2ecf20Sopenharmony_ci	 */
16818c2ecf20Sopenharmony_ci	flush_workqueue(hdev->req_workqueue);
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	/* For controllers not using the management interface and that
16848c2ecf20Sopenharmony_ci	 * are brought up using legacy ioctl, set the HCI_BONDABLE bit
16858c2ecf20Sopenharmony_ci	 * so that pairing works for them. Once the management interface
16868c2ecf20Sopenharmony_ci	 * is in use this bit will be cleared again and userspace has
16878c2ecf20Sopenharmony_ci	 * to explicitly enable it.
16888c2ecf20Sopenharmony_ci	 */
16898c2ecf20Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
16908c2ecf20Sopenharmony_ci	    !hci_dev_test_flag(hdev, HCI_MGMT))
16918c2ecf20Sopenharmony_ci		hci_dev_set_flag(hdev, HCI_BONDABLE);
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci	err = hci_dev_do_open(hdev);
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_cidone:
16968c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
16978c2ecf20Sopenharmony_ci	return err;
16988c2ecf20Sopenharmony_ci}
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
17018c2ecf20Sopenharmony_cistatic void hci_pend_le_actions_clear(struct hci_dev *hdev)
17028c2ecf20Sopenharmony_ci{
17038c2ecf20Sopenharmony_ci	struct hci_conn_params *p;
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci	list_for_each_entry(p, &hdev->le_conn_params, list) {
17068c2ecf20Sopenharmony_ci		if (p->conn) {
17078c2ecf20Sopenharmony_ci			hci_conn_drop(p->conn);
17088c2ecf20Sopenharmony_ci			hci_conn_put(p->conn);
17098c2ecf20Sopenharmony_ci			p->conn = NULL;
17108c2ecf20Sopenharmony_ci		}
17118c2ecf20Sopenharmony_ci		list_del_init(&p->action);
17128c2ecf20Sopenharmony_ci	}
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci	BT_DBG("All LE pending actions cleared");
17158c2ecf20Sopenharmony_ci}
17168c2ecf20Sopenharmony_ci
17178c2ecf20Sopenharmony_ciint hci_dev_do_close(struct hci_dev *hdev)
17188c2ecf20Sopenharmony_ci{
17198c2ecf20Sopenharmony_ci	bool auto_off;
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	BT_DBG("%s %p", hdev->name, hdev);
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) &&
17248c2ecf20Sopenharmony_ci	    !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
17258c2ecf20Sopenharmony_ci	    test_bit(HCI_UP, &hdev->flags)) {
17268c2ecf20Sopenharmony_ci		/* Execute vendor specific shutdown routine */
17278c2ecf20Sopenharmony_ci		if (hdev->shutdown)
17288c2ecf20Sopenharmony_ci			hdev->shutdown(hdev);
17298c2ecf20Sopenharmony_ci	}
17308c2ecf20Sopenharmony_ci
17318c2ecf20Sopenharmony_ci	cancel_delayed_work(&hdev->power_off);
17328c2ecf20Sopenharmony_ci
17338c2ecf20Sopenharmony_ci	hci_request_cancel_all(hdev);
17348c2ecf20Sopenharmony_ci	hci_req_sync_lock(hdev);
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
17378c2ecf20Sopenharmony_ci		cancel_delayed_work_sync(&hdev->cmd_timer);
17388c2ecf20Sopenharmony_ci		hci_req_sync_unlock(hdev);
17398c2ecf20Sopenharmony_ci		return 0;
17408c2ecf20Sopenharmony_ci	}
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci	hci_leds_update_powered(hdev, false);
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	/* Flush RX and TX works */
17458c2ecf20Sopenharmony_ci	flush_work(&hdev->tx_work);
17468c2ecf20Sopenharmony_ci	flush_work(&hdev->rx_work);
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	if (hdev->discov_timeout > 0) {
17498c2ecf20Sopenharmony_ci		hdev->discov_timeout = 0;
17508c2ecf20Sopenharmony_ci		hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
17518c2ecf20Sopenharmony_ci		hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
17528c2ecf20Sopenharmony_ci	}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci	if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
17558c2ecf20Sopenharmony_ci		cancel_delayed_work(&hdev->service_cache);
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_MGMT)) {
17588c2ecf20Sopenharmony_ci		struct adv_info *adv_instance;
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci		cancel_delayed_work_sync(&hdev->rpa_expired);
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci		list_for_each_entry(adv_instance, &hdev->adv_instances, list)
17638c2ecf20Sopenharmony_ci			cancel_delayed_work_sync(&adv_instance->rpa_expired_cb);
17648c2ecf20Sopenharmony_ci	}
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_ci	/* Avoid potential lockdep warnings from the *_flush() calls by
17678c2ecf20Sopenharmony_ci	 * ensuring the workqueue is empty up front.
17688c2ecf20Sopenharmony_ci	 */
17698c2ecf20Sopenharmony_ci	drain_workqueue(hdev->workqueue);
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF);
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	if (!auto_off && hdev->dev_type == HCI_PRIMARY &&
17788c2ecf20Sopenharmony_ci	    !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
17798c2ecf20Sopenharmony_ci	    hci_dev_test_flag(hdev, HCI_MGMT))
17808c2ecf20Sopenharmony_ci		__mgmt_power_off(hdev);
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	hci_inquiry_cache_flush(hdev);
17838c2ecf20Sopenharmony_ci	hci_pend_le_actions_clear(hdev);
17848c2ecf20Sopenharmony_ci	hci_conn_hash_flush(hdev);
17858c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
17868c2ecf20Sopenharmony_ci
17878c2ecf20Sopenharmony_ci	smp_unregister(hdev);
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_ci	hci_sock_dev_event(hdev, HCI_DEV_DOWN);
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci	msft_do_close(hdev);
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci	if (hdev->flush)
17948c2ecf20Sopenharmony_ci		hdev->flush(hdev);
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci	/* Reset device */
17978c2ecf20Sopenharmony_ci	skb_queue_purge(&hdev->cmd_q);
17988c2ecf20Sopenharmony_ci	atomic_set(&hdev->cmd_cnt, 1);
17998c2ecf20Sopenharmony_ci	if (test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks) &&
18008c2ecf20Sopenharmony_ci	    !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
18018c2ecf20Sopenharmony_ci		set_bit(HCI_INIT, &hdev->flags);
18028c2ecf20Sopenharmony_ci		__hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT, NULL);
18038c2ecf20Sopenharmony_ci		clear_bit(HCI_INIT, &hdev->flags);
18048c2ecf20Sopenharmony_ci	}
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci	/* flush cmd  work */
18078c2ecf20Sopenharmony_ci	flush_work(&hdev->cmd_work);
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ci	/* Drop queues */
18108c2ecf20Sopenharmony_ci	skb_queue_purge(&hdev->rx_q);
18118c2ecf20Sopenharmony_ci	skb_queue_purge(&hdev->cmd_q);
18128c2ecf20Sopenharmony_ci	skb_queue_purge(&hdev->raw_q);
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci	/* Drop last sent command */
18158c2ecf20Sopenharmony_ci	if (hdev->sent_cmd) {
18168c2ecf20Sopenharmony_ci		cancel_delayed_work_sync(&hdev->cmd_timer);
18178c2ecf20Sopenharmony_ci		kfree_skb(hdev->sent_cmd);
18188c2ecf20Sopenharmony_ci		hdev->sent_cmd = NULL;
18198c2ecf20Sopenharmony_ci	}
18208c2ecf20Sopenharmony_ci
18218c2ecf20Sopenharmony_ci	clear_bit(HCI_RUNNING, &hdev->flags);
18228c2ecf20Sopenharmony_ci	hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
18238c2ecf20Sopenharmony_ci
18248c2ecf20Sopenharmony_ci	if (test_and_clear_bit(SUSPEND_POWERING_DOWN, hdev->suspend_tasks))
18258c2ecf20Sopenharmony_ci		wake_up(&hdev->suspend_wait_q);
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	/* After this point our queues are empty
18288c2ecf20Sopenharmony_ci	 * and no tasks are scheduled. */
18298c2ecf20Sopenharmony_ci	hdev->close(hdev);
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci	/* Clear flags */
18328c2ecf20Sopenharmony_ci	hdev->flags &= BIT(HCI_RAW);
18338c2ecf20Sopenharmony_ci	hci_dev_clear_volatile_flags(hdev);
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci	/* Controller radio is available but is currently powered down */
18368c2ecf20Sopenharmony_ci	hdev->amp_status = AMP_STATUS_POWERED_DOWN;
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci	memset(hdev->eir, 0, sizeof(hdev->eir));
18398c2ecf20Sopenharmony_ci	memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
18408c2ecf20Sopenharmony_ci	bacpy(&hdev->random_addr, BDADDR_ANY);
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_ci	hci_req_sync_unlock(hdev);
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
18458c2ecf20Sopenharmony_ci	return 0;
18468c2ecf20Sopenharmony_ci}
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_ciint hci_dev_close(__u16 dev)
18498c2ecf20Sopenharmony_ci{
18508c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
18518c2ecf20Sopenharmony_ci	int err;
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci	hdev = hci_dev_get(dev);
18548c2ecf20Sopenharmony_ci	if (!hdev)
18558c2ecf20Sopenharmony_ci		return -ENODEV;
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
18588c2ecf20Sopenharmony_ci		err = -EBUSY;
18598c2ecf20Sopenharmony_ci		goto done;
18608c2ecf20Sopenharmony_ci	}
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci	if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
18638c2ecf20Sopenharmony_ci		cancel_delayed_work(&hdev->power_off);
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci	err = hci_dev_do_close(hdev);
18668c2ecf20Sopenharmony_ci
18678c2ecf20Sopenharmony_cidone:
18688c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
18698c2ecf20Sopenharmony_ci	return err;
18708c2ecf20Sopenharmony_ci}
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_cistatic int hci_dev_do_reset(struct hci_dev *hdev)
18738c2ecf20Sopenharmony_ci{
18748c2ecf20Sopenharmony_ci	int ret;
18758c2ecf20Sopenharmony_ci
18768c2ecf20Sopenharmony_ci	BT_DBG("%s %p", hdev->name, hdev);
18778c2ecf20Sopenharmony_ci
18788c2ecf20Sopenharmony_ci	hci_req_sync_lock(hdev);
18798c2ecf20Sopenharmony_ci
18808c2ecf20Sopenharmony_ci	/* Drop queues */
18818c2ecf20Sopenharmony_ci	skb_queue_purge(&hdev->rx_q);
18828c2ecf20Sopenharmony_ci	skb_queue_purge(&hdev->cmd_q);
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci	/* Avoid potential lockdep warnings from the *_flush() calls by
18858c2ecf20Sopenharmony_ci	 * ensuring the workqueue is empty up front.
18868c2ecf20Sopenharmony_ci	 */
18878c2ecf20Sopenharmony_ci	drain_workqueue(hdev->workqueue);
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
18908c2ecf20Sopenharmony_ci	hci_inquiry_cache_flush(hdev);
18918c2ecf20Sopenharmony_ci	hci_conn_hash_flush(hdev);
18928c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
18938c2ecf20Sopenharmony_ci
18948c2ecf20Sopenharmony_ci	if (hdev->flush)
18958c2ecf20Sopenharmony_ci		hdev->flush(hdev);
18968c2ecf20Sopenharmony_ci
18978c2ecf20Sopenharmony_ci	atomic_set(&hdev->cmd_cnt, 1);
18988c2ecf20Sopenharmony_ci	hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0;
18998c2ecf20Sopenharmony_ci
19008c2ecf20Sopenharmony_ci	ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT, NULL);
19018c2ecf20Sopenharmony_ci
19028c2ecf20Sopenharmony_ci	hci_req_sync_unlock(hdev);
19038c2ecf20Sopenharmony_ci	return ret;
19048c2ecf20Sopenharmony_ci}
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ciint hci_dev_reset(__u16 dev)
19078c2ecf20Sopenharmony_ci{
19088c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
19098c2ecf20Sopenharmony_ci	int err;
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	hdev = hci_dev_get(dev);
19128c2ecf20Sopenharmony_ci	if (!hdev)
19138c2ecf20Sopenharmony_ci		return -ENODEV;
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	if (!test_bit(HCI_UP, &hdev->flags)) {
19168c2ecf20Sopenharmony_ci		err = -ENETDOWN;
19178c2ecf20Sopenharmony_ci		goto done;
19188c2ecf20Sopenharmony_ci	}
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
19218c2ecf20Sopenharmony_ci		err = -EBUSY;
19228c2ecf20Sopenharmony_ci		goto done;
19238c2ecf20Sopenharmony_ci	}
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
19268c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
19278c2ecf20Sopenharmony_ci		goto done;
19288c2ecf20Sopenharmony_ci	}
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	err = hci_dev_do_reset(hdev);
19318c2ecf20Sopenharmony_ci
19328c2ecf20Sopenharmony_cidone:
19338c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
19348c2ecf20Sopenharmony_ci	return err;
19358c2ecf20Sopenharmony_ci}
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_ciint hci_dev_reset_stat(__u16 dev)
19388c2ecf20Sopenharmony_ci{
19398c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
19408c2ecf20Sopenharmony_ci	int ret = 0;
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_ci	hdev = hci_dev_get(dev);
19438c2ecf20Sopenharmony_ci	if (!hdev)
19448c2ecf20Sopenharmony_ci		return -ENODEV;
19458c2ecf20Sopenharmony_ci
19468c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
19478c2ecf20Sopenharmony_ci		ret = -EBUSY;
19488c2ecf20Sopenharmony_ci		goto done;
19498c2ecf20Sopenharmony_ci	}
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
19528c2ecf20Sopenharmony_ci		ret = -EOPNOTSUPP;
19538c2ecf20Sopenharmony_ci		goto done;
19548c2ecf20Sopenharmony_ci	}
19558c2ecf20Sopenharmony_ci
19568c2ecf20Sopenharmony_ci	memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_cidone:
19598c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
19608c2ecf20Sopenharmony_ci	return ret;
19618c2ecf20Sopenharmony_ci}
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_cistatic void hci_update_scan_state(struct hci_dev *hdev, u8 scan)
19648c2ecf20Sopenharmony_ci{
19658c2ecf20Sopenharmony_ci	bool conn_changed, discov_changed;
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	BT_DBG("%s scan 0x%02x", hdev->name, scan);
19688c2ecf20Sopenharmony_ci
19698c2ecf20Sopenharmony_ci	if ((scan & SCAN_PAGE))
19708c2ecf20Sopenharmony_ci		conn_changed = !hci_dev_test_and_set_flag(hdev,
19718c2ecf20Sopenharmony_ci							  HCI_CONNECTABLE);
19728c2ecf20Sopenharmony_ci	else
19738c2ecf20Sopenharmony_ci		conn_changed = hci_dev_test_and_clear_flag(hdev,
19748c2ecf20Sopenharmony_ci							   HCI_CONNECTABLE);
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci	if ((scan & SCAN_INQUIRY)) {
19778c2ecf20Sopenharmony_ci		discov_changed = !hci_dev_test_and_set_flag(hdev,
19788c2ecf20Sopenharmony_ci							    HCI_DISCOVERABLE);
19798c2ecf20Sopenharmony_ci	} else {
19808c2ecf20Sopenharmony_ci		hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
19818c2ecf20Sopenharmony_ci		discov_changed = hci_dev_test_and_clear_flag(hdev,
19828c2ecf20Sopenharmony_ci							     HCI_DISCOVERABLE);
19838c2ecf20Sopenharmony_ci	}
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_MGMT))
19868c2ecf20Sopenharmony_ci		return;
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci	if (conn_changed || discov_changed) {
19898c2ecf20Sopenharmony_ci		/* In case this was disabled through mgmt */
19908c2ecf20Sopenharmony_ci		hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_ci		if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
19938c2ecf20Sopenharmony_ci			hci_req_update_adv_data(hdev, hdev->cur_adv_instance);
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci		mgmt_new_settings(hdev);
19968c2ecf20Sopenharmony_ci	}
19978c2ecf20Sopenharmony_ci}
19988c2ecf20Sopenharmony_ci
19998c2ecf20Sopenharmony_ciint hci_dev_cmd(unsigned int cmd, void __user *arg)
20008c2ecf20Sopenharmony_ci{
20018c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
20028c2ecf20Sopenharmony_ci	struct hci_dev_req dr;
20038c2ecf20Sopenharmony_ci	int err = 0;
20048c2ecf20Sopenharmony_ci
20058c2ecf20Sopenharmony_ci	if (copy_from_user(&dr, arg, sizeof(dr)))
20068c2ecf20Sopenharmony_ci		return -EFAULT;
20078c2ecf20Sopenharmony_ci
20088c2ecf20Sopenharmony_ci	hdev = hci_dev_get(dr.dev_id);
20098c2ecf20Sopenharmony_ci	if (!hdev)
20108c2ecf20Sopenharmony_ci		return -ENODEV;
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
20138c2ecf20Sopenharmony_ci		err = -EBUSY;
20148c2ecf20Sopenharmony_ci		goto done;
20158c2ecf20Sopenharmony_ci	}
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
20188c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
20198c2ecf20Sopenharmony_ci		goto done;
20208c2ecf20Sopenharmony_ci	}
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	if (hdev->dev_type != HCI_PRIMARY) {
20238c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
20248c2ecf20Sopenharmony_ci		goto done;
20258c2ecf20Sopenharmony_ci	}
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
20288c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
20298c2ecf20Sopenharmony_ci		goto done;
20308c2ecf20Sopenharmony_ci	}
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci	switch (cmd) {
20338c2ecf20Sopenharmony_ci	case HCISETAUTH:
20348c2ecf20Sopenharmony_ci		err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
20358c2ecf20Sopenharmony_ci				   HCI_INIT_TIMEOUT, NULL);
20368c2ecf20Sopenharmony_ci		break;
20378c2ecf20Sopenharmony_ci
20388c2ecf20Sopenharmony_ci	case HCISETENCRYPT:
20398c2ecf20Sopenharmony_ci		if (!lmp_encrypt_capable(hdev)) {
20408c2ecf20Sopenharmony_ci			err = -EOPNOTSUPP;
20418c2ecf20Sopenharmony_ci			break;
20428c2ecf20Sopenharmony_ci		}
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci		if (!test_bit(HCI_AUTH, &hdev->flags)) {
20458c2ecf20Sopenharmony_ci			/* Auth must be enabled first */
20468c2ecf20Sopenharmony_ci			err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
20478c2ecf20Sopenharmony_ci					   HCI_INIT_TIMEOUT, NULL);
20488c2ecf20Sopenharmony_ci			if (err)
20498c2ecf20Sopenharmony_ci				break;
20508c2ecf20Sopenharmony_ci		}
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci		err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt,
20538c2ecf20Sopenharmony_ci				   HCI_INIT_TIMEOUT, NULL);
20548c2ecf20Sopenharmony_ci		break;
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	case HCISETSCAN:
20578c2ecf20Sopenharmony_ci		err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt,
20588c2ecf20Sopenharmony_ci				   HCI_INIT_TIMEOUT, NULL);
20598c2ecf20Sopenharmony_ci
20608c2ecf20Sopenharmony_ci		/* Ensure that the connectable and discoverable states
20618c2ecf20Sopenharmony_ci		 * get correctly modified as this was a non-mgmt change.
20628c2ecf20Sopenharmony_ci		 */
20638c2ecf20Sopenharmony_ci		if (!err)
20648c2ecf20Sopenharmony_ci			hci_update_scan_state(hdev, dr.dev_opt);
20658c2ecf20Sopenharmony_ci		break;
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ci	case HCISETLINKPOL:
20688c2ecf20Sopenharmony_ci		err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt,
20698c2ecf20Sopenharmony_ci				   HCI_INIT_TIMEOUT, NULL);
20708c2ecf20Sopenharmony_ci		break;
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_ci	case HCISETLINKMODE:
20738c2ecf20Sopenharmony_ci		hdev->link_mode = ((__u16) dr.dev_opt) &
20748c2ecf20Sopenharmony_ci					(HCI_LM_MASTER | HCI_LM_ACCEPT);
20758c2ecf20Sopenharmony_ci		break;
20768c2ecf20Sopenharmony_ci
20778c2ecf20Sopenharmony_ci	case HCISETPTYPE:
20788c2ecf20Sopenharmony_ci		if (hdev->pkt_type == (__u16) dr.dev_opt)
20798c2ecf20Sopenharmony_ci			break;
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_ci		hdev->pkt_type = (__u16) dr.dev_opt;
20828c2ecf20Sopenharmony_ci		mgmt_phy_configuration_changed(hdev, NULL);
20838c2ecf20Sopenharmony_ci		break;
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_ci	case HCISETACLMTU:
20868c2ecf20Sopenharmony_ci		hdev->acl_mtu  = *((__u16 *) &dr.dev_opt + 1);
20878c2ecf20Sopenharmony_ci		hdev->acl_pkts = *((__u16 *) &dr.dev_opt + 0);
20888c2ecf20Sopenharmony_ci		break;
20898c2ecf20Sopenharmony_ci
20908c2ecf20Sopenharmony_ci	case HCISETSCOMTU:
20918c2ecf20Sopenharmony_ci		hdev->sco_mtu  = *((__u16 *) &dr.dev_opt + 1);
20928c2ecf20Sopenharmony_ci		hdev->sco_pkts = *((__u16 *) &dr.dev_opt + 0);
20938c2ecf20Sopenharmony_ci		break;
20948c2ecf20Sopenharmony_ci
20958c2ecf20Sopenharmony_ci	default:
20968c2ecf20Sopenharmony_ci		err = -EINVAL;
20978c2ecf20Sopenharmony_ci		break;
20988c2ecf20Sopenharmony_ci	}
20998c2ecf20Sopenharmony_ci
21008c2ecf20Sopenharmony_cidone:
21018c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
21028c2ecf20Sopenharmony_ci	return err;
21038c2ecf20Sopenharmony_ci}
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ciint hci_get_dev_list(void __user *arg)
21068c2ecf20Sopenharmony_ci{
21078c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
21088c2ecf20Sopenharmony_ci	struct hci_dev_list_req *dl;
21098c2ecf20Sopenharmony_ci	struct hci_dev_req *dr;
21108c2ecf20Sopenharmony_ci	int n = 0, size, err;
21118c2ecf20Sopenharmony_ci	__u16 dev_num;
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci	if (get_user(dev_num, (__u16 __user *) arg))
21148c2ecf20Sopenharmony_ci		return -EFAULT;
21158c2ecf20Sopenharmony_ci
21168c2ecf20Sopenharmony_ci	if (!dev_num || dev_num > (PAGE_SIZE * 2) / sizeof(*dr))
21178c2ecf20Sopenharmony_ci		return -EINVAL;
21188c2ecf20Sopenharmony_ci
21198c2ecf20Sopenharmony_ci	size = sizeof(*dl) + dev_num * sizeof(*dr);
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_ci	dl = kzalloc(size, GFP_KERNEL);
21228c2ecf20Sopenharmony_ci	if (!dl)
21238c2ecf20Sopenharmony_ci		return -ENOMEM;
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_ci	dr = dl->dev_req;
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci	read_lock(&hci_dev_list_lock);
21288c2ecf20Sopenharmony_ci	list_for_each_entry(hdev, &hci_dev_list, list) {
21298c2ecf20Sopenharmony_ci		unsigned long flags = hdev->flags;
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci		/* When the auto-off is configured it means the transport
21328c2ecf20Sopenharmony_ci		 * is running, but in that case still indicate that the
21338c2ecf20Sopenharmony_ci		 * device is actually down.
21348c2ecf20Sopenharmony_ci		 */
21358c2ecf20Sopenharmony_ci		if (hci_dev_test_flag(hdev, HCI_AUTO_OFF))
21368c2ecf20Sopenharmony_ci			flags &= ~BIT(HCI_UP);
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ci		(dr + n)->dev_id  = hdev->id;
21398c2ecf20Sopenharmony_ci		(dr + n)->dev_opt = flags;
21408c2ecf20Sopenharmony_ci
21418c2ecf20Sopenharmony_ci		if (++n >= dev_num)
21428c2ecf20Sopenharmony_ci			break;
21438c2ecf20Sopenharmony_ci	}
21448c2ecf20Sopenharmony_ci	read_unlock(&hci_dev_list_lock);
21458c2ecf20Sopenharmony_ci
21468c2ecf20Sopenharmony_ci	dl->dev_num = n;
21478c2ecf20Sopenharmony_ci	size = sizeof(*dl) + n * sizeof(*dr);
21488c2ecf20Sopenharmony_ci
21498c2ecf20Sopenharmony_ci	err = copy_to_user(arg, dl, size);
21508c2ecf20Sopenharmony_ci	kfree(dl);
21518c2ecf20Sopenharmony_ci
21528c2ecf20Sopenharmony_ci	return err ? -EFAULT : 0;
21538c2ecf20Sopenharmony_ci}
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ciint hci_get_dev_info(void __user *arg)
21568c2ecf20Sopenharmony_ci{
21578c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
21588c2ecf20Sopenharmony_ci	struct hci_dev_info di;
21598c2ecf20Sopenharmony_ci	unsigned long flags;
21608c2ecf20Sopenharmony_ci	int err = 0;
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_ci	if (copy_from_user(&di, arg, sizeof(di)))
21638c2ecf20Sopenharmony_ci		return -EFAULT;
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci	hdev = hci_dev_get(di.dev_id);
21668c2ecf20Sopenharmony_ci	if (!hdev)
21678c2ecf20Sopenharmony_ci		return -ENODEV;
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci	/* When the auto-off is configured it means the transport
21708c2ecf20Sopenharmony_ci	 * is running, but in that case still indicate that the
21718c2ecf20Sopenharmony_ci	 * device is actually down.
21728c2ecf20Sopenharmony_ci	 */
21738c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_AUTO_OFF))
21748c2ecf20Sopenharmony_ci		flags = hdev->flags & ~BIT(HCI_UP);
21758c2ecf20Sopenharmony_ci	else
21768c2ecf20Sopenharmony_ci		flags = hdev->flags;
21778c2ecf20Sopenharmony_ci
21788c2ecf20Sopenharmony_ci	strscpy(di.name, hdev->name, sizeof(di.name));
21798c2ecf20Sopenharmony_ci	di.bdaddr   = hdev->bdaddr;
21808c2ecf20Sopenharmony_ci	di.type     = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4);
21818c2ecf20Sopenharmony_ci	di.flags    = flags;
21828c2ecf20Sopenharmony_ci	di.pkt_type = hdev->pkt_type;
21838c2ecf20Sopenharmony_ci	if (lmp_bredr_capable(hdev)) {
21848c2ecf20Sopenharmony_ci		di.acl_mtu  = hdev->acl_mtu;
21858c2ecf20Sopenharmony_ci		di.acl_pkts = hdev->acl_pkts;
21868c2ecf20Sopenharmony_ci		di.sco_mtu  = hdev->sco_mtu;
21878c2ecf20Sopenharmony_ci		di.sco_pkts = hdev->sco_pkts;
21888c2ecf20Sopenharmony_ci	} else {
21898c2ecf20Sopenharmony_ci		di.acl_mtu  = hdev->le_mtu;
21908c2ecf20Sopenharmony_ci		di.acl_pkts = hdev->le_pkts;
21918c2ecf20Sopenharmony_ci		di.sco_mtu  = 0;
21928c2ecf20Sopenharmony_ci		di.sco_pkts = 0;
21938c2ecf20Sopenharmony_ci	}
21948c2ecf20Sopenharmony_ci	di.link_policy = hdev->link_policy;
21958c2ecf20Sopenharmony_ci	di.link_mode   = hdev->link_mode;
21968c2ecf20Sopenharmony_ci
21978c2ecf20Sopenharmony_ci	memcpy(&di.stat, &hdev->stat, sizeof(di.stat));
21988c2ecf20Sopenharmony_ci	memcpy(&di.features, &hdev->features, sizeof(di.features));
21998c2ecf20Sopenharmony_ci
22008c2ecf20Sopenharmony_ci	if (copy_to_user(arg, &di, sizeof(di)))
22018c2ecf20Sopenharmony_ci		err = -EFAULT;
22028c2ecf20Sopenharmony_ci
22038c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
22048c2ecf20Sopenharmony_ci
22058c2ecf20Sopenharmony_ci	return err;
22068c2ecf20Sopenharmony_ci}
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_ci/* ---- Interface to HCI drivers ---- */
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_cistatic int hci_rfkill_set_block(void *data, bool blocked)
22118c2ecf20Sopenharmony_ci{
22128c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
22138c2ecf20Sopenharmony_ci
22148c2ecf20Sopenharmony_ci	BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
22178c2ecf20Sopenharmony_ci		return -EBUSY;
22188c2ecf20Sopenharmony_ci
22198c2ecf20Sopenharmony_ci	if (blocked) {
22208c2ecf20Sopenharmony_ci		hci_dev_set_flag(hdev, HCI_RFKILLED);
22218c2ecf20Sopenharmony_ci		if (!hci_dev_test_flag(hdev, HCI_SETUP) &&
22228c2ecf20Sopenharmony_ci		    !hci_dev_test_flag(hdev, HCI_CONFIG))
22238c2ecf20Sopenharmony_ci			hci_dev_do_close(hdev);
22248c2ecf20Sopenharmony_ci	} else {
22258c2ecf20Sopenharmony_ci		hci_dev_clear_flag(hdev, HCI_RFKILLED);
22268c2ecf20Sopenharmony_ci	}
22278c2ecf20Sopenharmony_ci
22288c2ecf20Sopenharmony_ci	return 0;
22298c2ecf20Sopenharmony_ci}
22308c2ecf20Sopenharmony_ci
22318c2ecf20Sopenharmony_cistatic const struct rfkill_ops hci_rfkill_ops = {
22328c2ecf20Sopenharmony_ci	.set_block = hci_rfkill_set_block,
22338c2ecf20Sopenharmony_ci};
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_cistatic void hci_power_on(struct work_struct *work)
22368c2ecf20Sopenharmony_ci{
22378c2ecf20Sopenharmony_ci	struct hci_dev *hdev = container_of(work, struct hci_dev, power_on);
22388c2ecf20Sopenharmony_ci	int err;
22398c2ecf20Sopenharmony_ci
22408c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_ci	if (test_bit(HCI_UP, &hdev->flags) &&
22438c2ecf20Sopenharmony_ci	    hci_dev_test_flag(hdev, HCI_MGMT) &&
22448c2ecf20Sopenharmony_ci	    hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
22458c2ecf20Sopenharmony_ci		cancel_delayed_work(&hdev->power_off);
22468c2ecf20Sopenharmony_ci		hci_req_sync_lock(hdev);
22478c2ecf20Sopenharmony_ci		err = __hci_req_hci_power_on(hdev);
22488c2ecf20Sopenharmony_ci		hci_req_sync_unlock(hdev);
22498c2ecf20Sopenharmony_ci		mgmt_power_on(hdev, err);
22508c2ecf20Sopenharmony_ci		return;
22518c2ecf20Sopenharmony_ci	}
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci	err = hci_dev_do_open(hdev);
22548c2ecf20Sopenharmony_ci	if (err < 0) {
22558c2ecf20Sopenharmony_ci		hci_dev_lock(hdev);
22568c2ecf20Sopenharmony_ci		mgmt_set_powered_failed(hdev, err);
22578c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
22588c2ecf20Sopenharmony_ci		return;
22598c2ecf20Sopenharmony_ci	}
22608c2ecf20Sopenharmony_ci
22618c2ecf20Sopenharmony_ci	/* During the HCI setup phase, a few error conditions are
22628c2ecf20Sopenharmony_ci	 * ignored and they need to be checked now. If they are still
22638c2ecf20Sopenharmony_ci	 * valid, it is important to turn the device back off.
22648c2ecf20Sopenharmony_ci	 */
22658c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_RFKILLED) ||
22668c2ecf20Sopenharmony_ci	    hci_dev_test_flag(hdev, HCI_UNCONFIGURED) ||
22678c2ecf20Sopenharmony_ci	    (hdev->dev_type == HCI_PRIMARY &&
22688c2ecf20Sopenharmony_ci	     !bacmp(&hdev->bdaddr, BDADDR_ANY) &&
22698c2ecf20Sopenharmony_ci	     !bacmp(&hdev->static_addr, BDADDR_ANY))) {
22708c2ecf20Sopenharmony_ci		hci_dev_clear_flag(hdev, HCI_AUTO_OFF);
22718c2ecf20Sopenharmony_ci		hci_dev_do_close(hdev);
22728c2ecf20Sopenharmony_ci	} else if (hci_dev_test_flag(hdev, HCI_AUTO_OFF)) {
22738c2ecf20Sopenharmony_ci		queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
22748c2ecf20Sopenharmony_ci				   HCI_AUTO_OFF_TIMEOUT);
22758c2ecf20Sopenharmony_ci	}
22768c2ecf20Sopenharmony_ci
22778c2ecf20Sopenharmony_ci	if (hci_dev_test_and_clear_flag(hdev, HCI_SETUP)) {
22788c2ecf20Sopenharmony_ci		/* For unconfigured devices, set the HCI_RAW flag
22798c2ecf20Sopenharmony_ci		 * so that userspace can easily identify them.
22808c2ecf20Sopenharmony_ci		 */
22818c2ecf20Sopenharmony_ci		if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
22828c2ecf20Sopenharmony_ci			set_bit(HCI_RAW, &hdev->flags);
22838c2ecf20Sopenharmony_ci
22848c2ecf20Sopenharmony_ci		/* For fully configured devices, this will send
22858c2ecf20Sopenharmony_ci		 * the Index Added event. For unconfigured devices,
22868c2ecf20Sopenharmony_ci		 * it will send Unconfigued Index Added event.
22878c2ecf20Sopenharmony_ci		 *
22888c2ecf20Sopenharmony_ci		 * Devices with HCI_QUIRK_RAW_DEVICE are ignored
22898c2ecf20Sopenharmony_ci		 * and no event will be send.
22908c2ecf20Sopenharmony_ci		 */
22918c2ecf20Sopenharmony_ci		mgmt_index_added(hdev);
22928c2ecf20Sopenharmony_ci	} else if (hci_dev_test_and_clear_flag(hdev, HCI_CONFIG)) {
22938c2ecf20Sopenharmony_ci		/* When the controller is now configured, then it
22948c2ecf20Sopenharmony_ci		 * is important to clear the HCI_RAW flag.
22958c2ecf20Sopenharmony_ci		 */
22968c2ecf20Sopenharmony_ci		if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
22978c2ecf20Sopenharmony_ci			clear_bit(HCI_RAW, &hdev->flags);
22988c2ecf20Sopenharmony_ci
22998c2ecf20Sopenharmony_ci		/* Powering on the controller with HCI_CONFIG set only
23008c2ecf20Sopenharmony_ci		 * happens with the transition from unconfigured to
23018c2ecf20Sopenharmony_ci		 * configured. This will send the Index Added event.
23028c2ecf20Sopenharmony_ci		 */
23038c2ecf20Sopenharmony_ci		mgmt_index_added(hdev);
23048c2ecf20Sopenharmony_ci	}
23058c2ecf20Sopenharmony_ci}
23068c2ecf20Sopenharmony_ci
23078c2ecf20Sopenharmony_cistatic void hci_power_off(struct work_struct *work)
23088c2ecf20Sopenharmony_ci{
23098c2ecf20Sopenharmony_ci	struct hci_dev *hdev = container_of(work, struct hci_dev,
23108c2ecf20Sopenharmony_ci					    power_off.work);
23118c2ecf20Sopenharmony_ci
23128c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
23138c2ecf20Sopenharmony_ci
23148c2ecf20Sopenharmony_ci	hci_dev_do_close(hdev);
23158c2ecf20Sopenharmony_ci}
23168c2ecf20Sopenharmony_ci
23178c2ecf20Sopenharmony_cistatic void hci_error_reset(struct work_struct *work)
23188c2ecf20Sopenharmony_ci{
23198c2ecf20Sopenharmony_ci	struct hci_dev *hdev = container_of(work, struct hci_dev, error_reset);
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci	hci_dev_hold(hdev);
23228c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
23238c2ecf20Sopenharmony_ci
23248c2ecf20Sopenharmony_ci	if (hdev->hw_error)
23258c2ecf20Sopenharmony_ci		hdev->hw_error(hdev, hdev->hw_error_code);
23268c2ecf20Sopenharmony_ci	else
23278c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "hardware error 0x%2.2x", hdev->hw_error_code);
23288c2ecf20Sopenharmony_ci
23298c2ecf20Sopenharmony_ci	if (!hci_dev_do_close(hdev))
23308c2ecf20Sopenharmony_ci		hci_dev_do_open(hdev);
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
23338c2ecf20Sopenharmony_ci}
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_civoid hci_uuids_clear(struct hci_dev *hdev)
23368c2ecf20Sopenharmony_ci{
23378c2ecf20Sopenharmony_ci	struct bt_uuid *uuid, *tmp;
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_ci	list_for_each_entry_safe(uuid, tmp, &hdev->uuids, list) {
23408c2ecf20Sopenharmony_ci		list_del(&uuid->list);
23418c2ecf20Sopenharmony_ci		kfree(uuid);
23428c2ecf20Sopenharmony_ci	}
23438c2ecf20Sopenharmony_ci}
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_civoid hci_link_keys_clear(struct hci_dev *hdev)
23468c2ecf20Sopenharmony_ci{
23478c2ecf20Sopenharmony_ci	struct link_key *key, *tmp;
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci	list_for_each_entry_safe(key, tmp, &hdev->link_keys, list) {
23508c2ecf20Sopenharmony_ci		list_del_rcu(&key->list);
23518c2ecf20Sopenharmony_ci		kfree_rcu(key, rcu);
23528c2ecf20Sopenharmony_ci	}
23538c2ecf20Sopenharmony_ci}
23548c2ecf20Sopenharmony_ci
23558c2ecf20Sopenharmony_civoid hci_smp_ltks_clear(struct hci_dev *hdev)
23568c2ecf20Sopenharmony_ci{
23578c2ecf20Sopenharmony_ci	struct smp_ltk *k, *tmp;
23588c2ecf20Sopenharmony_ci
23598c2ecf20Sopenharmony_ci	list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
23608c2ecf20Sopenharmony_ci		list_del_rcu(&k->list);
23618c2ecf20Sopenharmony_ci		kfree_rcu(k, rcu);
23628c2ecf20Sopenharmony_ci	}
23638c2ecf20Sopenharmony_ci}
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_civoid hci_smp_irks_clear(struct hci_dev *hdev)
23668c2ecf20Sopenharmony_ci{
23678c2ecf20Sopenharmony_ci	struct smp_irk *k, *tmp;
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_ci	list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
23708c2ecf20Sopenharmony_ci		list_del_rcu(&k->list);
23718c2ecf20Sopenharmony_ci		kfree_rcu(k, rcu);
23728c2ecf20Sopenharmony_ci	}
23738c2ecf20Sopenharmony_ci}
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_civoid hci_blocked_keys_clear(struct hci_dev *hdev)
23768c2ecf20Sopenharmony_ci{
23778c2ecf20Sopenharmony_ci	struct blocked_key *b, *tmp;
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci	list_for_each_entry_safe(b, tmp, &hdev->blocked_keys, list) {
23808c2ecf20Sopenharmony_ci		list_del_rcu(&b->list);
23818c2ecf20Sopenharmony_ci		kfree_rcu(b, rcu);
23828c2ecf20Sopenharmony_ci	}
23838c2ecf20Sopenharmony_ci}
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_cibool hci_is_blocked_key(struct hci_dev *hdev, u8 type, u8 val[16])
23868c2ecf20Sopenharmony_ci{
23878c2ecf20Sopenharmony_ci	bool blocked = false;
23888c2ecf20Sopenharmony_ci	struct blocked_key *b;
23898c2ecf20Sopenharmony_ci
23908c2ecf20Sopenharmony_ci	rcu_read_lock();
23918c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(b, &hdev->blocked_keys, list) {
23928c2ecf20Sopenharmony_ci		if (b->type == type && !memcmp(b->val, val, sizeof(b->val))) {
23938c2ecf20Sopenharmony_ci			blocked = true;
23948c2ecf20Sopenharmony_ci			break;
23958c2ecf20Sopenharmony_ci		}
23968c2ecf20Sopenharmony_ci	}
23978c2ecf20Sopenharmony_ci
23988c2ecf20Sopenharmony_ci	rcu_read_unlock();
23998c2ecf20Sopenharmony_ci	return blocked;
24008c2ecf20Sopenharmony_ci}
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_cistruct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
24038c2ecf20Sopenharmony_ci{
24048c2ecf20Sopenharmony_ci	struct link_key *k;
24058c2ecf20Sopenharmony_ci
24068c2ecf20Sopenharmony_ci	rcu_read_lock();
24078c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(k, &hdev->link_keys, list) {
24088c2ecf20Sopenharmony_ci		if (bacmp(bdaddr, &k->bdaddr) == 0) {
24098c2ecf20Sopenharmony_ci			rcu_read_unlock();
24108c2ecf20Sopenharmony_ci
24118c2ecf20Sopenharmony_ci			if (hci_is_blocked_key(hdev,
24128c2ecf20Sopenharmony_ci					       HCI_BLOCKED_KEY_TYPE_LINKKEY,
24138c2ecf20Sopenharmony_ci					       k->val)) {
24148c2ecf20Sopenharmony_ci				bt_dev_warn_ratelimited(hdev,
24158c2ecf20Sopenharmony_ci							"Link key blocked for %pMR",
24168c2ecf20Sopenharmony_ci							&k->bdaddr);
24178c2ecf20Sopenharmony_ci				return NULL;
24188c2ecf20Sopenharmony_ci			}
24198c2ecf20Sopenharmony_ci
24208c2ecf20Sopenharmony_ci			return k;
24218c2ecf20Sopenharmony_ci		}
24228c2ecf20Sopenharmony_ci	}
24238c2ecf20Sopenharmony_ci	rcu_read_unlock();
24248c2ecf20Sopenharmony_ci
24258c2ecf20Sopenharmony_ci	return NULL;
24268c2ecf20Sopenharmony_ci}
24278c2ecf20Sopenharmony_ci
24288c2ecf20Sopenharmony_cistatic bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
24298c2ecf20Sopenharmony_ci			       u8 key_type, u8 old_key_type)
24308c2ecf20Sopenharmony_ci{
24318c2ecf20Sopenharmony_ci	/* Legacy key */
24328c2ecf20Sopenharmony_ci	if (key_type < 0x03)
24338c2ecf20Sopenharmony_ci		return true;
24348c2ecf20Sopenharmony_ci
24358c2ecf20Sopenharmony_ci	/* Debug keys are insecure so don't store them persistently */
24368c2ecf20Sopenharmony_ci	if (key_type == HCI_LK_DEBUG_COMBINATION)
24378c2ecf20Sopenharmony_ci		return false;
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ci	/* Changed combination key and there's no previous one */
24408c2ecf20Sopenharmony_ci	if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
24418c2ecf20Sopenharmony_ci		return false;
24428c2ecf20Sopenharmony_ci
24438c2ecf20Sopenharmony_ci	/* Security mode 3 case */
24448c2ecf20Sopenharmony_ci	if (!conn)
24458c2ecf20Sopenharmony_ci		return true;
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci	/* BR/EDR key derived using SC from an LE link */
24488c2ecf20Sopenharmony_ci	if (conn->type == LE_LINK)
24498c2ecf20Sopenharmony_ci		return true;
24508c2ecf20Sopenharmony_ci
24518c2ecf20Sopenharmony_ci	/* Neither local nor remote side had no-bonding as requirement */
24528c2ecf20Sopenharmony_ci	if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
24538c2ecf20Sopenharmony_ci		return true;
24548c2ecf20Sopenharmony_ci
24558c2ecf20Sopenharmony_ci	/* Local side had dedicated bonding as requirement */
24568c2ecf20Sopenharmony_ci	if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
24578c2ecf20Sopenharmony_ci		return true;
24588c2ecf20Sopenharmony_ci
24598c2ecf20Sopenharmony_ci	/* Remote side had dedicated bonding as requirement */
24608c2ecf20Sopenharmony_ci	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
24618c2ecf20Sopenharmony_ci		return true;
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_ci	/* If none of the above criteria match, then don't store the key
24648c2ecf20Sopenharmony_ci	 * persistently */
24658c2ecf20Sopenharmony_ci	return false;
24668c2ecf20Sopenharmony_ci}
24678c2ecf20Sopenharmony_ci
24688c2ecf20Sopenharmony_cistatic u8 ltk_role(u8 type)
24698c2ecf20Sopenharmony_ci{
24708c2ecf20Sopenharmony_ci	if (type == SMP_LTK)
24718c2ecf20Sopenharmony_ci		return HCI_ROLE_MASTER;
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci	return HCI_ROLE_SLAVE;
24748c2ecf20Sopenharmony_ci}
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_cistruct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
24778c2ecf20Sopenharmony_ci			     u8 addr_type, u8 role)
24788c2ecf20Sopenharmony_ci{
24798c2ecf20Sopenharmony_ci	struct smp_ltk *k;
24808c2ecf20Sopenharmony_ci
24818c2ecf20Sopenharmony_ci	rcu_read_lock();
24828c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
24838c2ecf20Sopenharmony_ci		if (addr_type != k->bdaddr_type || bacmp(bdaddr, &k->bdaddr))
24848c2ecf20Sopenharmony_ci			continue;
24858c2ecf20Sopenharmony_ci
24868c2ecf20Sopenharmony_ci		if (smp_ltk_is_sc(k) || ltk_role(k->type) == role) {
24878c2ecf20Sopenharmony_ci			rcu_read_unlock();
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_ci			if (hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_LTK,
24908c2ecf20Sopenharmony_ci					       k->val)) {
24918c2ecf20Sopenharmony_ci				bt_dev_warn_ratelimited(hdev,
24928c2ecf20Sopenharmony_ci							"LTK blocked for %pMR",
24938c2ecf20Sopenharmony_ci							&k->bdaddr);
24948c2ecf20Sopenharmony_ci				return NULL;
24958c2ecf20Sopenharmony_ci			}
24968c2ecf20Sopenharmony_ci
24978c2ecf20Sopenharmony_ci			return k;
24988c2ecf20Sopenharmony_ci		}
24998c2ecf20Sopenharmony_ci	}
25008c2ecf20Sopenharmony_ci	rcu_read_unlock();
25018c2ecf20Sopenharmony_ci
25028c2ecf20Sopenharmony_ci	return NULL;
25038c2ecf20Sopenharmony_ci}
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_cistruct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa)
25068c2ecf20Sopenharmony_ci{
25078c2ecf20Sopenharmony_ci	struct smp_irk *irk_to_return = NULL;
25088c2ecf20Sopenharmony_ci	struct smp_irk *irk;
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci	rcu_read_lock();
25118c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
25128c2ecf20Sopenharmony_ci		if (!bacmp(&irk->rpa, rpa)) {
25138c2ecf20Sopenharmony_ci			irk_to_return = irk;
25148c2ecf20Sopenharmony_ci			goto done;
25158c2ecf20Sopenharmony_ci		}
25168c2ecf20Sopenharmony_ci	}
25178c2ecf20Sopenharmony_ci
25188c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
25198c2ecf20Sopenharmony_ci		if (smp_irk_matches(hdev, irk->val, rpa)) {
25208c2ecf20Sopenharmony_ci			bacpy(&irk->rpa, rpa);
25218c2ecf20Sopenharmony_ci			irk_to_return = irk;
25228c2ecf20Sopenharmony_ci			goto done;
25238c2ecf20Sopenharmony_ci		}
25248c2ecf20Sopenharmony_ci	}
25258c2ecf20Sopenharmony_ci
25268c2ecf20Sopenharmony_cidone:
25278c2ecf20Sopenharmony_ci	if (irk_to_return && hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK,
25288c2ecf20Sopenharmony_ci						irk_to_return->val)) {
25298c2ecf20Sopenharmony_ci		bt_dev_warn_ratelimited(hdev, "Identity key blocked for %pMR",
25308c2ecf20Sopenharmony_ci					&irk_to_return->bdaddr);
25318c2ecf20Sopenharmony_ci		irk_to_return = NULL;
25328c2ecf20Sopenharmony_ci	}
25338c2ecf20Sopenharmony_ci
25348c2ecf20Sopenharmony_ci	rcu_read_unlock();
25358c2ecf20Sopenharmony_ci
25368c2ecf20Sopenharmony_ci	return irk_to_return;
25378c2ecf20Sopenharmony_ci}
25388c2ecf20Sopenharmony_ci
25398c2ecf20Sopenharmony_cistruct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
25408c2ecf20Sopenharmony_ci				     u8 addr_type)
25418c2ecf20Sopenharmony_ci{
25428c2ecf20Sopenharmony_ci	struct smp_irk *irk_to_return = NULL;
25438c2ecf20Sopenharmony_ci	struct smp_irk *irk;
25448c2ecf20Sopenharmony_ci
25458c2ecf20Sopenharmony_ci	/* Identity Address must be public or static random */
25468c2ecf20Sopenharmony_ci	if (addr_type == ADDR_LE_DEV_RANDOM && (bdaddr->b[5] & 0xc0) != 0xc0)
25478c2ecf20Sopenharmony_ci		return NULL;
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci	rcu_read_lock();
25508c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
25518c2ecf20Sopenharmony_ci		if (addr_type == irk->addr_type &&
25528c2ecf20Sopenharmony_ci		    bacmp(bdaddr, &irk->bdaddr) == 0) {
25538c2ecf20Sopenharmony_ci			irk_to_return = irk;
25548c2ecf20Sopenharmony_ci			goto done;
25558c2ecf20Sopenharmony_ci		}
25568c2ecf20Sopenharmony_ci	}
25578c2ecf20Sopenharmony_ci
25588c2ecf20Sopenharmony_cidone:
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_ci	if (irk_to_return && hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK,
25618c2ecf20Sopenharmony_ci						irk_to_return->val)) {
25628c2ecf20Sopenharmony_ci		bt_dev_warn_ratelimited(hdev, "Identity key blocked for %pMR",
25638c2ecf20Sopenharmony_ci					&irk_to_return->bdaddr);
25648c2ecf20Sopenharmony_ci		irk_to_return = NULL;
25658c2ecf20Sopenharmony_ci	}
25668c2ecf20Sopenharmony_ci
25678c2ecf20Sopenharmony_ci	rcu_read_unlock();
25688c2ecf20Sopenharmony_ci
25698c2ecf20Sopenharmony_ci	return irk_to_return;
25708c2ecf20Sopenharmony_ci}
25718c2ecf20Sopenharmony_ci
25728c2ecf20Sopenharmony_cistruct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
25738c2ecf20Sopenharmony_ci				  bdaddr_t *bdaddr, u8 *val, u8 type,
25748c2ecf20Sopenharmony_ci				  u8 pin_len, bool *persistent)
25758c2ecf20Sopenharmony_ci{
25768c2ecf20Sopenharmony_ci	struct link_key *key, *old_key;
25778c2ecf20Sopenharmony_ci	u8 old_key_type;
25788c2ecf20Sopenharmony_ci
25798c2ecf20Sopenharmony_ci	old_key = hci_find_link_key(hdev, bdaddr);
25808c2ecf20Sopenharmony_ci	if (old_key) {
25818c2ecf20Sopenharmony_ci		old_key_type = old_key->type;
25828c2ecf20Sopenharmony_ci		key = old_key;
25838c2ecf20Sopenharmony_ci	} else {
25848c2ecf20Sopenharmony_ci		old_key_type = conn ? conn->key_type : 0xff;
25858c2ecf20Sopenharmony_ci		key = kzalloc(sizeof(*key), GFP_KERNEL);
25868c2ecf20Sopenharmony_ci		if (!key)
25878c2ecf20Sopenharmony_ci			return NULL;
25888c2ecf20Sopenharmony_ci		list_add_rcu(&key->list, &hdev->link_keys);
25898c2ecf20Sopenharmony_ci	}
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci	BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
25928c2ecf20Sopenharmony_ci
25938c2ecf20Sopenharmony_ci	/* Some buggy controller combinations generate a changed
25948c2ecf20Sopenharmony_ci	 * combination key for legacy pairing even when there's no
25958c2ecf20Sopenharmony_ci	 * previous key */
25968c2ecf20Sopenharmony_ci	if (type == HCI_LK_CHANGED_COMBINATION &&
25978c2ecf20Sopenharmony_ci	    (!conn || conn->remote_auth == 0xff) && old_key_type == 0xff) {
25988c2ecf20Sopenharmony_ci		type = HCI_LK_COMBINATION;
25998c2ecf20Sopenharmony_ci		if (conn)
26008c2ecf20Sopenharmony_ci			conn->key_type = type;
26018c2ecf20Sopenharmony_ci	}
26028c2ecf20Sopenharmony_ci
26038c2ecf20Sopenharmony_ci	bacpy(&key->bdaddr, bdaddr);
26048c2ecf20Sopenharmony_ci	memcpy(key->val, val, HCI_LINK_KEY_SIZE);
26058c2ecf20Sopenharmony_ci	key->pin_len = pin_len;
26068c2ecf20Sopenharmony_ci
26078c2ecf20Sopenharmony_ci	if (type == HCI_LK_CHANGED_COMBINATION)
26088c2ecf20Sopenharmony_ci		key->type = old_key_type;
26098c2ecf20Sopenharmony_ci	else
26108c2ecf20Sopenharmony_ci		key->type = type;
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_ci	if (persistent)
26138c2ecf20Sopenharmony_ci		*persistent = hci_persistent_key(hdev, conn, type,
26148c2ecf20Sopenharmony_ci						 old_key_type);
26158c2ecf20Sopenharmony_ci
26168c2ecf20Sopenharmony_ci	return key;
26178c2ecf20Sopenharmony_ci}
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_cistruct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
26208c2ecf20Sopenharmony_ci			    u8 addr_type, u8 type, u8 authenticated,
26218c2ecf20Sopenharmony_ci			    u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand)
26228c2ecf20Sopenharmony_ci{
26238c2ecf20Sopenharmony_ci	struct smp_ltk *key, *old_key;
26248c2ecf20Sopenharmony_ci	u8 role = ltk_role(type);
26258c2ecf20Sopenharmony_ci
26268c2ecf20Sopenharmony_ci	old_key = hci_find_ltk(hdev, bdaddr, addr_type, role);
26278c2ecf20Sopenharmony_ci	if (old_key)
26288c2ecf20Sopenharmony_ci		key = old_key;
26298c2ecf20Sopenharmony_ci	else {
26308c2ecf20Sopenharmony_ci		key = kzalloc(sizeof(*key), GFP_KERNEL);
26318c2ecf20Sopenharmony_ci		if (!key)
26328c2ecf20Sopenharmony_ci			return NULL;
26338c2ecf20Sopenharmony_ci		list_add_rcu(&key->list, &hdev->long_term_keys);
26348c2ecf20Sopenharmony_ci	}
26358c2ecf20Sopenharmony_ci
26368c2ecf20Sopenharmony_ci	bacpy(&key->bdaddr, bdaddr);
26378c2ecf20Sopenharmony_ci	key->bdaddr_type = addr_type;
26388c2ecf20Sopenharmony_ci	memcpy(key->val, tk, sizeof(key->val));
26398c2ecf20Sopenharmony_ci	key->authenticated = authenticated;
26408c2ecf20Sopenharmony_ci	key->ediv = ediv;
26418c2ecf20Sopenharmony_ci	key->rand = rand;
26428c2ecf20Sopenharmony_ci	key->enc_size = enc_size;
26438c2ecf20Sopenharmony_ci	key->type = type;
26448c2ecf20Sopenharmony_ci
26458c2ecf20Sopenharmony_ci	return key;
26468c2ecf20Sopenharmony_ci}
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_cistruct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
26498c2ecf20Sopenharmony_ci			    u8 addr_type, u8 val[16], bdaddr_t *rpa)
26508c2ecf20Sopenharmony_ci{
26518c2ecf20Sopenharmony_ci	struct smp_irk *irk;
26528c2ecf20Sopenharmony_ci
26538c2ecf20Sopenharmony_ci	irk = hci_find_irk_by_addr(hdev, bdaddr, addr_type);
26548c2ecf20Sopenharmony_ci	if (!irk) {
26558c2ecf20Sopenharmony_ci		irk = kzalloc(sizeof(*irk), GFP_KERNEL);
26568c2ecf20Sopenharmony_ci		if (!irk)
26578c2ecf20Sopenharmony_ci			return NULL;
26588c2ecf20Sopenharmony_ci
26598c2ecf20Sopenharmony_ci		bacpy(&irk->bdaddr, bdaddr);
26608c2ecf20Sopenharmony_ci		irk->addr_type = addr_type;
26618c2ecf20Sopenharmony_ci
26628c2ecf20Sopenharmony_ci		list_add_rcu(&irk->list, &hdev->identity_resolving_keys);
26638c2ecf20Sopenharmony_ci	}
26648c2ecf20Sopenharmony_ci
26658c2ecf20Sopenharmony_ci	memcpy(irk->val, val, 16);
26668c2ecf20Sopenharmony_ci	bacpy(&irk->rpa, rpa);
26678c2ecf20Sopenharmony_ci
26688c2ecf20Sopenharmony_ci	return irk;
26698c2ecf20Sopenharmony_ci}
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_ciint hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
26728c2ecf20Sopenharmony_ci{
26738c2ecf20Sopenharmony_ci	struct link_key *key;
26748c2ecf20Sopenharmony_ci
26758c2ecf20Sopenharmony_ci	key = hci_find_link_key(hdev, bdaddr);
26768c2ecf20Sopenharmony_ci	if (!key)
26778c2ecf20Sopenharmony_ci		return -ENOENT;
26788c2ecf20Sopenharmony_ci
26798c2ecf20Sopenharmony_ci	BT_DBG("%s removing %pMR", hdev->name, bdaddr);
26808c2ecf20Sopenharmony_ci
26818c2ecf20Sopenharmony_ci	list_del_rcu(&key->list);
26828c2ecf20Sopenharmony_ci	kfree_rcu(key, rcu);
26838c2ecf20Sopenharmony_ci
26848c2ecf20Sopenharmony_ci	return 0;
26858c2ecf20Sopenharmony_ci}
26868c2ecf20Sopenharmony_ci
26878c2ecf20Sopenharmony_ciint hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
26888c2ecf20Sopenharmony_ci{
26898c2ecf20Sopenharmony_ci	struct smp_ltk *k, *tmp;
26908c2ecf20Sopenharmony_ci	int removed = 0;
26918c2ecf20Sopenharmony_ci
26928c2ecf20Sopenharmony_ci	list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
26938c2ecf20Sopenharmony_ci		if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type)
26948c2ecf20Sopenharmony_ci			continue;
26958c2ecf20Sopenharmony_ci
26968c2ecf20Sopenharmony_ci		BT_DBG("%s removing %pMR", hdev->name, bdaddr);
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci		list_del_rcu(&k->list);
26998c2ecf20Sopenharmony_ci		kfree_rcu(k, rcu);
27008c2ecf20Sopenharmony_ci		removed++;
27018c2ecf20Sopenharmony_ci	}
27028c2ecf20Sopenharmony_ci
27038c2ecf20Sopenharmony_ci	return removed ? 0 : -ENOENT;
27048c2ecf20Sopenharmony_ci}
27058c2ecf20Sopenharmony_ci
27068c2ecf20Sopenharmony_civoid hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type)
27078c2ecf20Sopenharmony_ci{
27088c2ecf20Sopenharmony_ci	struct smp_irk *k, *tmp;
27098c2ecf20Sopenharmony_ci
27108c2ecf20Sopenharmony_ci	list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
27118c2ecf20Sopenharmony_ci		if (bacmp(bdaddr, &k->bdaddr) || k->addr_type != addr_type)
27128c2ecf20Sopenharmony_ci			continue;
27138c2ecf20Sopenharmony_ci
27148c2ecf20Sopenharmony_ci		BT_DBG("%s removing %pMR", hdev->name, bdaddr);
27158c2ecf20Sopenharmony_ci
27168c2ecf20Sopenharmony_ci		list_del_rcu(&k->list);
27178c2ecf20Sopenharmony_ci		kfree_rcu(k, rcu);
27188c2ecf20Sopenharmony_ci	}
27198c2ecf20Sopenharmony_ci}
27208c2ecf20Sopenharmony_ci
27218c2ecf20Sopenharmony_cibool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
27228c2ecf20Sopenharmony_ci{
27238c2ecf20Sopenharmony_ci	struct smp_ltk *k;
27248c2ecf20Sopenharmony_ci	struct smp_irk *irk;
27258c2ecf20Sopenharmony_ci	u8 addr_type;
27268c2ecf20Sopenharmony_ci
27278c2ecf20Sopenharmony_ci	if (type == BDADDR_BREDR) {
27288c2ecf20Sopenharmony_ci		if (hci_find_link_key(hdev, bdaddr))
27298c2ecf20Sopenharmony_ci			return true;
27308c2ecf20Sopenharmony_ci		return false;
27318c2ecf20Sopenharmony_ci	}
27328c2ecf20Sopenharmony_ci
27338c2ecf20Sopenharmony_ci	/* Convert to HCI addr type which struct smp_ltk uses */
27348c2ecf20Sopenharmony_ci	if (type == BDADDR_LE_PUBLIC)
27358c2ecf20Sopenharmony_ci		addr_type = ADDR_LE_DEV_PUBLIC;
27368c2ecf20Sopenharmony_ci	else
27378c2ecf20Sopenharmony_ci		addr_type = ADDR_LE_DEV_RANDOM;
27388c2ecf20Sopenharmony_ci
27398c2ecf20Sopenharmony_ci	irk = hci_get_irk(hdev, bdaddr, addr_type);
27408c2ecf20Sopenharmony_ci	if (irk) {
27418c2ecf20Sopenharmony_ci		bdaddr = &irk->bdaddr;
27428c2ecf20Sopenharmony_ci		addr_type = irk->addr_type;
27438c2ecf20Sopenharmony_ci	}
27448c2ecf20Sopenharmony_ci
27458c2ecf20Sopenharmony_ci	rcu_read_lock();
27468c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
27478c2ecf20Sopenharmony_ci		if (k->bdaddr_type == addr_type && !bacmp(bdaddr, &k->bdaddr)) {
27488c2ecf20Sopenharmony_ci			rcu_read_unlock();
27498c2ecf20Sopenharmony_ci			return true;
27508c2ecf20Sopenharmony_ci		}
27518c2ecf20Sopenharmony_ci	}
27528c2ecf20Sopenharmony_ci	rcu_read_unlock();
27538c2ecf20Sopenharmony_ci
27548c2ecf20Sopenharmony_ci	return false;
27558c2ecf20Sopenharmony_ci}
27568c2ecf20Sopenharmony_ci
27578c2ecf20Sopenharmony_ci/* HCI command timer function */
27588c2ecf20Sopenharmony_cistatic void hci_cmd_timeout(struct work_struct *work)
27598c2ecf20Sopenharmony_ci{
27608c2ecf20Sopenharmony_ci	struct hci_dev *hdev = container_of(work, struct hci_dev,
27618c2ecf20Sopenharmony_ci					    cmd_timer.work);
27628c2ecf20Sopenharmony_ci
27638c2ecf20Sopenharmony_ci	if (hdev->sent_cmd) {
27648c2ecf20Sopenharmony_ci		struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data;
27658c2ecf20Sopenharmony_ci		u16 opcode = __le16_to_cpu(sent->opcode);
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode);
27688c2ecf20Sopenharmony_ci	} else {
27698c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "command tx timeout");
27708c2ecf20Sopenharmony_ci	}
27718c2ecf20Sopenharmony_ci
27728c2ecf20Sopenharmony_ci	if (hdev->cmd_timeout)
27738c2ecf20Sopenharmony_ci		hdev->cmd_timeout(hdev);
27748c2ecf20Sopenharmony_ci
27758c2ecf20Sopenharmony_ci	atomic_set(&hdev->cmd_cnt, 1);
27768c2ecf20Sopenharmony_ci	queue_work(hdev->workqueue, &hdev->cmd_work);
27778c2ecf20Sopenharmony_ci}
27788c2ecf20Sopenharmony_ci
27798c2ecf20Sopenharmony_cistruct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
27808c2ecf20Sopenharmony_ci					  bdaddr_t *bdaddr, u8 bdaddr_type)
27818c2ecf20Sopenharmony_ci{
27828c2ecf20Sopenharmony_ci	struct oob_data *data;
27838c2ecf20Sopenharmony_ci
27848c2ecf20Sopenharmony_ci	list_for_each_entry(data, &hdev->remote_oob_data, list) {
27858c2ecf20Sopenharmony_ci		if (bacmp(bdaddr, &data->bdaddr) != 0)
27868c2ecf20Sopenharmony_ci			continue;
27878c2ecf20Sopenharmony_ci		if (data->bdaddr_type != bdaddr_type)
27888c2ecf20Sopenharmony_ci			continue;
27898c2ecf20Sopenharmony_ci		return data;
27908c2ecf20Sopenharmony_ci	}
27918c2ecf20Sopenharmony_ci
27928c2ecf20Sopenharmony_ci	return NULL;
27938c2ecf20Sopenharmony_ci}
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_ciint hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
27968c2ecf20Sopenharmony_ci			       u8 bdaddr_type)
27978c2ecf20Sopenharmony_ci{
27988c2ecf20Sopenharmony_ci	struct oob_data *data;
27998c2ecf20Sopenharmony_ci
28008c2ecf20Sopenharmony_ci	data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
28018c2ecf20Sopenharmony_ci	if (!data)
28028c2ecf20Sopenharmony_ci		return -ENOENT;
28038c2ecf20Sopenharmony_ci
28048c2ecf20Sopenharmony_ci	BT_DBG("%s removing %pMR (%u)", hdev->name, bdaddr, bdaddr_type);
28058c2ecf20Sopenharmony_ci
28068c2ecf20Sopenharmony_ci	list_del(&data->list);
28078c2ecf20Sopenharmony_ci	kfree(data);
28088c2ecf20Sopenharmony_ci
28098c2ecf20Sopenharmony_ci	return 0;
28108c2ecf20Sopenharmony_ci}
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_civoid hci_remote_oob_data_clear(struct hci_dev *hdev)
28138c2ecf20Sopenharmony_ci{
28148c2ecf20Sopenharmony_ci	struct oob_data *data, *n;
28158c2ecf20Sopenharmony_ci
28168c2ecf20Sopenharmony_ci	list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) {
28178c2ecf20Sopenharmony_ci		list_del(&data->list);
28188c2ecf20Sopenharmony_ci		kfree(data);
28198c2ecf20Sopenharmony_ci	}
28208c2ecf20Sopenharmony_ci}
28218c2ecf20Sopenharmony_ci
28228c2ecf20Sopenharmony_ciint hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
28238c2ecf20Sopenharmony_ci			    u8 bdaddr_type, u8 *hash192, u8 *rand192,
28248c2ecf20Sopenharmony_ci			    u8 *hash256, u8 *rand256)
28258c2ecf20Sopenharmony_ci{
28268c2ecf20Sopenharmony_ci	struct oob_data *data;
28278c2ecf20Sopenharmony_ci
28288c2ecf20Sopenharmony_ci	data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
28298c2ecf20Sopenharmony_ci	if (!data) {
28308c2ecf20Sopenharmony_ci		data = kmalloc(sizeof(*data), GFP_KERNEL);
28318c2ecf20Sopenharmony_ci		if (!data)
28328c2ecf20Sopenharmony_ci			return -ENOMEM;
28338c2ecf20Sopenharmony_ci
28348c2ecf20Sopenharmony_ci		bacpy(&data->bdaddr, bdaddr);
28358c2ecf20Sopenharmony_ci		data->bdaddr_type = bdaddr_type;
28368c2ecf20Sopenharmony_ci		list_add(&data->list, &hdev->remote_oob_data);
28378c2ecf20Sopenharmony_ci	}
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_ci	if (hash192 && rand192) {
28408c2ecf20Sopenharmony_ci		memcpy(data->hash192, hash192, sizeof(data->hash192));
28418c2ecf20Sopenharmony_ci		memcpy(data->rand192, rand192, sizeof(data->rand192));
28428c2ecf20Sopenharmony_ci		if (hash256 && rand256)
28438c2ecf20Sopenharmony_ci			data->present = 0x03;
28448c2ecf20Sopenharmony_ci	} else {
28458c2ecf20Sopenharmony_ci		memset(data->hash192, 0, sizeof(data->hash192));
28468c2ecf20Sopenharmony_ci		memset(data->rand192, 0, sizeof(data->rand192));
28478c2ecf20Sopenharmony_ci		if (hash256 && rand256)
28488c2ecf20Sopenharmony_ci			data->present = 0x02;
28498c2ecf20Sopenharmony_ci		else
28508c2ecf20Sopenharmony_ci			data->present = 0x00;
28518c2ecf20Sopenharmony_ci	}
28528c2ecf20Sopenharmony_ci
28538c2ecf20Sopenharmony_ci	if (hash256 && rand256) {
28548c2ecf20Sopenharmony_ci		memcpy(data->hash256, hash256, sizeof(data->hash256));
28558c2ecf20Sopenharmony_ci		memcpy(data->rand256, rand256, sizeof(data->rand256));
28568c2ecf20Sopenharmony_ci	} else {
28578c2ecf20Sopenharmony_ci		memset(data->hash256, 0, sizeof(data->hash256));
28588c2ecf20Sopenharmony_ci		memset(data->rand256, 0, sizeof(data->rand256));
28598c2ecf20Sopenharmony_ci		if (hash192 && rand192)
28608c2ecf20Sopenharmony_ci			data->present = 0x01;
28618c2ecf20Sopenharmony_ci	}
28628c2ecf20Sopenharmony_ci
28638c2ecf20Sopenharmony_ci	BT_DBG("%s for %pMR", hdev->name, bdaddr);
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_ci	return 0;
28668c2ecf20Sopenharmony_ci}
28678c2ecf20Sopenharmony_ci
28688c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
28698c2ecf20Sopenharmony_cistruct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance)
28708c2ecf20Sopenharmony_ci{
28718c2ecf20Sopenharmony_ci	struct adv_info *adv_instance;
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_ci	list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
28748c2ecf20Sopenharmony_ci		if (adv_instance->instance == instance)
28758c2ecf20Sopenharmony_ci			return adv_instance;
28768c2ecf20Sopenharmony_ci	}
28778c2ecf20Sopenharmony_ci
28788c2ecf20Sopenharmony_ci	return NULL;
28798c2ecf20Sopenharmony_ci}
28808c2ecf20Sopenharmony_ci
28818c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
28828c2ecf20Sopenharmony_cistruct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance)
28838c2ecf20Sopenharmony_ci{
28848c2ecf20Sopenharmony_ci	struct adv_info *cur_instance;
28858c2ecf20Sopenharmony_ci
28868c2ecf20Sopenharmony_ci	cur_instance = hci_find_adv_instance(hdev, instance);
28878c2ecf20Sopenharmony_ci	if (!cur_instance)
28888c2ecf20Sopenharmony_ci		return NULL;
28898c2ecf20Sopenharmony_ci
28908c2ecf20Sopenharmony_ci	if (cur_instance == list_last_entry(&hdev->adv_instances,
28918c2ecf20Sopenharmony_ci					    struct adv_info, list))
28928c2ecf20Sopenharmony_ci		return list_first_entry(&hdev->adv_instances,
28938c2ecf20Sopenharmony_ci						 struct adv_info, list);
28948c2ecf20Sopenharmony_ci	else
28958c2ecf20Sopenharmony_ci		return list_next_entry(cur_instance, list);
28968c2ecf20Sopenharmony_ci}
28978c2ecf20Sopenharmony_ci
28988c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
28998c2ecf20Sopenharmony_ciint hci_remove_adv_instance(struct hci_dev *hdev, u8 instance)
29008c2ecf20Sopenharmony_ci{
29018c2ecf20Sopenharmony_ci	struct adv_info *adv_instance;
29028c2ecf20Sopenharmony_ci
29038c2ecf20Sopenharmony_ci	adv_instance = hci_find_adv_instance(hdev, instance);
29048c2ecf20Sopenharmony_ci	if (!adv_instance)
29058c2ecf20Sopenharmony_ci		return -ENOENT;
29068c2ecf20Sopenharmony_ci
29078c2ecf20Sopenharmony_ci	BT_DBG("%s removing %dMR", hdev->name, instance);
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci	if (hdev->cur_adv_instance == instance) {
29108c2ecf20Sopenharmony_ci		if (hdev->adv_instance_timeout) {
29118c2ecf20Sopenharmony_ci			cancel_delayed_work(&hdev->adv_instance_expire);
29128c2ecf20Sopenharmony_ci			hdev->adv_instance_timeout = 0;
29138c2ecf20Sopenharmony_ci		}
29148c2ecf20Sopenharmony_ci		hdev->cur_adv_instance = 0x00;
29158c2ecf20Sopenharmony_ci	}
29168c2ecf20Sopenharmony_ci
29178c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&adv_instance->rpa_expired_cb);
29188c2ecf20Sopenharmony_ci
29198c2ecf20Sopenharmony_ci	list_del(&adv_instance->list);
29208c2ecf20Sopenharmony_ci	kfree(adv_instance);
29218c2ecf20Sopenharmony_ci
29228c2ecf20Sopenharmony_ci	hdev->adv_instance_cnt--;
29238c2ecf20Sopenharmony_ci
29248c2ecf20Sopenharmony_ci	return 0;
29258c2ecf20Sopenharmony_ci}
29268c2ecf20Sopenharmony_ci
29278c2ecf20Sopenharmony_civoid hci_adv_instances_set_rpa_expired(struct hci_dev *hdev, bool rpa_expired)
29288c2ecf20Sopenharmony_ci{
29298c2ecf20Sopenharmony_ci	struct adv_info *adv_instance, *n;
29308c2ecf20Sopenharmony_ci
29318c2ecf20Sopenharmony_ci	list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list)
29328c2ecf20Sopenharmony_ci		adv_instance->rpa_expired = rpa_expired;
29338c2ecf20Sopenharmony_ci}
29348c2ecf20Sopenharmony_ci
29358c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
29368c2ecf20Sopenharmony_civoid hci_adv_instances_clear(struct hci_dev *hdev)
29378c2ecf20Sopenharmony_ci{
29388c2ecf20Sopenharmony_ci	struct adv_info *adv_instance, *n;
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_ci	if (hdev->adv_instance_timeout) {
29418c2ecf20Sopenharmony_ci		cancel_delayed_work(&hdev->adv_instance_expire);
29428c2ecf20Sopenharmony_ci		hdev->adv_instance_timeout = 0;
29438c2ecf20Sopenharmony_ci	}
29448c2ecf20Sopenharmony_ci
29458c2ecf20Sopenharmony_ci	list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) {
29468c2ecf20Sopenharmony_ci		cancel_delayed_work_sync(&adv_instance->rpa_expired_cb);
29478c2ecf20Sopenharmony_ci		list_del(&adv_instance->list);
29488c2ecf20Sopenharmony_ci		kfree(adv_instance);
29498c2ecf20Sopenharmony_ci	}
29508c2ecf20Sopenharmony_ci
29518c2ecf20Sopenharmony_ci	hdev->adv_instance_cnt = 0;
29528c2ecf20Sopenharmony_ci	hdev->cur_adv_instance = 0x00;
29538c2ecf20Sopenharmony_ci}
29548c2ecf20Sopenharmony_ci
29558c2ecf20Sopenharmony_cistatic void adv_instance_rpa_expired(struct work_struct *work)
29568c2ecf20Sopenharmony_ci{
29578c2ecf20Sopenharmony_ci	struct adv_info *adv_instance = container_of(work, struct adv_info,
29588c2ecf20Sopenharmony_ci						     rpa_expired_cb.work);
29598c2ecf20Sopenharmony_ci
29608c2ecf20Sopenharmony_ci	BT_DBG("");
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_ci	adv_instance->rpa_expired = true;
29638c2ecf20Sopenharmony_ci}
29648c2ecf20Sopenharmony_ci
29658c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
29668c2ecf20Sopenharmony_ciint hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
29678c2ecf20Sopenharmony_ci			 u16 adv_data_len, u8 *adv_data,
29688c2ecf20Sopenharmony_ci			 u16 scan_rsp_len, u8 *scan_rsp_data,
29698c2ecf20Sopenharmony_ci			 u16 timeout, u16 duration)
29708c2ecf20Sopenharmony_ci{
29718c2ecf20Sopenharmony_ci	struct adv_info *adv_instance;
29728c2ecf20Sopenharmony_ci
29738c2ecf20Sopenharmony_ci	adv_instance = hci_find_adv_instance(hdev, instance);
29748c2ecf20Sopenharmony_ci	if (adv_instance) {
29758c2ecf20Sopenharmony_ci		memset(adv_instance->adv_data, 0,
29768c2ecf20Sopenharmony_ci		       sizeof(adv_instance->adv_data));
29778c2ecf20Sopenharmony_ci		memset(adv_instance->scan_rsp_data, 0,
29788c2ecf20Sopenharmony_ci		       sizeof(adv_instance->scan_rsp_data));
29798c2ecf20Sopenharmony_ci	} else {
29808c2ecf20Sopenharmony_ci		if (hdev->adv_instance_cnt >= hdev->le_num_of_adv_sets ||
29818c2ecf20Sopenharmony_ci		    instance < 1 || instance > hdev->le_num_of_adv_sets)
29828c2ecf20Sopenharmony_ci			return -EOVERFLOW;
29838c2ecf20Sopenharmony_ci
29848c2ecf20Sopenharmony_ci		adv_instance = kzalloc(sizeof(*adv_instance), GFP_KERNEL);
29858c2ecf20Sopenharmony_ci		if (!adv_instance)
29868c2ecf20Sopenharmony_ci			return -ENOMEM;
29878c2ecf20Sopenharmony_ci
29888c2ecf20Sopenharmony_ci		adv_instance->pending = true;
29898c2ecf20Sopenharmony_ci		adv_instance->instance = instance;
29908c2ecf20Sopenharmony_ci		list_add(&adv_instance->list, &hdev->adv_instances);
29918c2ecf20Sopenharmony_ci		hdev->adv_instance_cnt++;
29928c2ecf20Sopenharmony_ci	}
29938c2ecf20Sopenharmony_ci
29948c2ecf20Sopenharmony_ci	adv_instance->flags = flags;
29958c2ecf20Sopenharmony_ci	adv_instance->adv_data_len = adv_data_len;
29968c2ecf20Sopenharmony_ci	adv_instance->scan_rsp_len = scan_rsp_len;
29978c2ecf20Sopenharmony_ci
29988c2ecf20Sopenharmony_ci	if (adv_data_len)
29998c2ecf20Sopenharmony_ci		memcpy(adv_instance->adv_data, adv_data, adv_data_len);
30008c2ecf20Sopenharmony_ci
30018c2ecf20Sopenharmony_ci	if (scan_rsp_len)
30028c2ecf20Sopenharmony_ci		memcpy(adv_instance->scan_rsp_data,
30038c2ecf20Sopenharmony_ci		       scan_rsp_data, scan_rsp_len);
30048c2ecf20Sopenharmony_ci
30058c2ecf20Sopenharmony_ci	adv_instance->timeout = timeout;
30068c2ecf20Sopenharmony_ci	adv_instance->remaining_time = timeout;
30078c2ecf20Sopenharmony_ci
30088c2ecf20Sopenharmony_ci	if (duration == 0)
30098c2ecf20Sopenharmony_ci		adv_instance->duration = hdev->def_multi_adv_rotation_duration;
30108c2ecf20Sopenharmony_ci	else
30118c2ecf20Sopenharmony_ci		adv_instance->duration = duration;
30128c2ecf20Sopenharmony_ci
30138c2ecf20Sopenharmony_ci	adv_instance->tx_power = HCI_TX_POWER_INVALID;
30148c2ecf20Sopenharmony_ci
30158c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&adv_instance->rpa_expired_cb,
30168c2ecf20Sopenharmony_ci			  adv_instance_rpa_expired);
30178c2ecf20Sopenharmony_ci
30188c2ecf20Sopenharmony_ci	BT_DBG("%s for %dMR", hdev->name, instance);
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_ci	return 0;
30218c2ecf20Sopenharmony_ci}
30228c2ecf20Sopenharmony_ci
30238c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
30248c2ecf20Sopenharmony_civoid hci_adv_monitors_clear(struct hci_dev *hdev)
30258c2ecf20Sopenharmony_ci{
30268c2ecf20Sopenharmony_ci	struct adv_monitor *monitor;
30278c2ecf20Sopenharmony_ci	int handle;
30288c2ecf20Sopenharmony_ci
30298c2ecf20Sopenharmony_ci	idr_for_each_entry(&hdev->adv_monitors_idr, monitor, handle)
30308c2ecf20Sopenharmony_ci		hci_free_adv_monitor(monitor);
30318c2ecf20Sopenharmony_ci
30328c2ecf20Sopenharmony_ci	idr_destroy(&hdev->adv_monitors_idr);
30338c2ecf20Sopenharmony_ci}
30348c2ecf20Sopenharmony_ci
30358c2ecf20Sopenharmony_civoid hci_free_adv_monitor(struct adv_monitor *monitor)
30368c2ecf20Sopenharmony_ci{
30378c2ecf20Sopenharmony_ci	struct adv_pattern *pattern;
30388c2ecf20Sopenharmony_ci	struct adv_pattern *tmp;
30398c2ecf20Sopenharmony_ci
30408c2ecf20Sopenharmony_ci	if (!monitor)
30418c2ecf20Sopenharmony_ci		return;
30428c2ecf20Sopenharmony_ci
30438c2ecf20Sopenharmony_ci	list_for_each_entry_safe(pattern, tmp, &monitor->patterns, list)
30448c2ecf20Sopenharmony_ci		kfree(pattern);
30458c2ecf20Sopenharmony_ci
30468c2ecf20Sopenharmony_ci	kfree(monitor);
30478c2ecf20Sopenharmony_ci}
30488c2ecf20Sopenharmony_ci
30498c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
30508c2ecf20Sopenharmony_ciint hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
30518c2ecf20Sopenharmony_ci{
30528c2ecf20Sopenharmony_ci	int min, max, handle;
30538c2ecf20Sopenharmony_ci
30548c2ecf20Sopenharmony_ci	if (!monitor)
30558c2ecf20Sopenharmony_ci		return -EINVAL;
30568c2ecf20Sopenharmony_ci
30578c2ecf20Sopenharmony_ci	min = HCI_MIN_ADV_MONITOR_HANDLE;
30588c2ecf20Sopenharmony_ci	max = HCI_MIN_ADV_MONITOR_HANDLE + HCI_MAX_ADV_MONITOR_NUM_HANDLES;
30598c2ecf20Sopenharmony_ci	handle = idr_alloc(&hdev->adv_monitors_idr, monitor, min, max,
30608c2ecf20Sopenharmony_ci			   GFP_KERNEL);
30618c2ecf20Sopenharmony_ci	if (handle < 0)
30628c2ecf20Sopenharmony_ci		return handle;
30638c2ecf20Sopenharmony_ci
30648c2ecf20Sopenharmony_ci	hdev->adv_monitors_cnt++;
30658c2ecf20Sopenharmony_ci	monitor->handle = handle;
30668c2ecf20Sopenharmony_ci
30678c2ecf20Sopenharmony_ci	hci_update_background_scan(hdev);
30688c2ecf20Sopenharmony_ci
30698c2ecf20Sopenharmony_ci	return 0;
30708c2ecf20Sopenharmony_ci}
30718c2ecf20Sopenharmony_ci
30728c2ecf20Sopenharmony_cistatic int free_adv_monitor(int id, void *ptr, void *data)
30738c2ecf20Sopenharmony_ci{
30748c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
30758c2ecf20Sopenharmony_ci	struct adv_monitor *monitor = ptr;
30768c2ecf20Sopenharmony_ci
30778c2ecf20Sopenharmony_ci	idr_remove(&hdev->adv_monitors_idr, monitor->handle);
30788c2ecf20Sopenharmony_ci	hci_free_adv_monitor(monitor);
30798c2ecf20Sopenharmony_ci	hdev->adv_monitors_cnt--;
30808c2ecf20Sopenharmony_ci
30818c2ecf20Sopenharmony_ci	return 0;
30828c2ecf20Sopenharmony_ci}
30838c2ecf20Sopenharmony_ci
30848c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
30858c2ecf20Sopenharmony_ciint hci_remove_adv_monitor(struct hci_dev *hdev, u16 handle)
30868c2ecf20Sopenharmony_ci{
30878c2ecf20Sopenharmony_ci	struct adv_monitor *monitor;
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_ci	if (handle) {
30908c2ecf20Sopenharmony_ci		monitor = idr_find(&hdev->adv_monitors_idr, handle);
30918c2ecf20Sopenharmony_ci		if (!monitor)
30928c2ecf20Sopenharmony_ci			return -ENOENT;
30938c2ecf20Sopenharmony_ci
30948c2ecf20Sopenharmony_ci		idr_remove(&hdev->adv_monitors_idr, monitor->handle);
30958c2ecf20Sopenharmony_ci		hci_free_adv_monitor(monitor);
30968c2ecf20Sopenharmony_ci		hdev->adv_monitors_cnt--;
30978c2ecf20Sopenharmony_ci	} else {
30988c2ecf20Sopenharmony_ci		/* Remove all monitors if handle is 0. */
30998c2ecf20Sopenharmony_ci		idr_for_each(&hdev->adv_monitors_idr, &free_adv_monitor, hdev);
31008c2ecf20Sopenharmony_ci	}
31018c2ecf20Sopenharmony_ci
31028c2ecf20Sopenharmony_ci	hci_update_background_scan(hdev);
31038c2ecf20Sopenharmony_ci
31048c2ecf20Sopenharmony_ci	return 0;
31058c2ecf20Sopenharmony_ci}
31068c2ecf20Sopenharmony_ci
31078c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
31088c2ecf20Sopenharmony_cibool hci_is_adv_monitoring(struct hci_dev *hdev)
31098c2ecf20Sopenharmony_ci{
31108c2ecf20Sopenharmony_ci	return !idr_is_empty(&hdev->adv_monitors_idr);
31118c2ecf20Sopenharmony_ci}
31128c2ecf20Sopenharmony_ci
31138c2ecf20Sopenharmony_cistruct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list,
31148c2ecf20Sopenharmony_ci					 bdaddr_t *bdaddr, u8 type)
31158c2ecf20Sopenharmony_ci{
31168c2ecf20Sopenharmony_ci	struct bdaddr_list *b;
31178c2ecf20Sopenharmony_ci
31188c2ecf20Sopenharmony_ci	list_for_each_entry(b, bdaddr_list, list) {
31198c2ecf20Sopenharmony_ci		if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
31208c2ecf20Sopenharmony_ci			return b;
31218c2ecf20Sopenharmony_ci	}
31228c2ecf20Sopenharmony_ci
31238c2ecf20Sopenharmony_ci	return NULL;
31248c2ecf20Sopenharmony_ci}
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_cistruct bdaddr_list_with_irk *hci_bdaddr_list_lookup_with_irk(
31278c2ecf20Sopenharmony_ci				struct list_head *bdaddr_list, bdaddr_t *bdaddr,
31288c2ecf20Sopenharmony_ci				u8 type)
31298c2ecf20Sopenharmony_ci{
31308c2ecf20Sopenharmony_ci	struct bdaddr_list_with_irk *b;
31318c2ecf20Sopenharmony_ci
31328c2ecf20Sopenharmony_ci	list_for_each_entry(b, bdaddr_list, list) {
31338c2ecf20Sopenharmony_ci		if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
31348c2ecf20Sopenharmony_ci			return b;
31358c2ecf20Sopenharmony_ci	}
31368c2ecf20Sopenharmony_ci
31378c2ecf20Sopenharmony_ci	return NULL;
31388c2ecf20Sopenharmony_ci}
31398c2ecf20Sopenharmony_ci
31408c2ecf20Sopenharmony_cistruct bdaddr_list_with_flags *
31418c2ecf20Sopenharmony_cihci_bdaddr_list_lookup_with_flags(struct list_head *bdaddr_list,
31428c2ecf20Sopenharmony_ci				  bdaddr_t *bdaddr, u8 type)
31438c2ecf20Sopenharmony_ci{
31448c2ecf20Sopenharmony_ci	struct bdaddr_list_with_flags *b;
31458c2ecf20Sopenharmony_ci
31468c2ecf20Sopenharmony_ci	list_for_each_entry(b, bdaddr_list, list) {
31478c2ecf20Sopenharmony_ci		if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
31488c2ecf20Sopenharmony_ci			return b;
31498c2ecf20Sopenharmony_ci	}
31508c2ecf20Sopenharmony_ci
31518c2ecf20Sopenharmony_ci	return NULL;
31528c2ecf20Sopenharmony_ci}
31538c2ecf20Sopenharmony_ci
31548c2ecf20Sopenharmony_civoid hci_bdaddr_list_clear(struct list_head *bdaddr_list)
31558c2ecf20Sopenharmony_ci{
31568c2ecf20Sopenharmony_ci	struct bdaddr_list *b, *n;
31578c2ecf20Sopenharmony_ci
31588c2ecf20Sopenharmony_ci	list_for_each_entry_safe(b, n, bdaddr_list, list) {
31598c2ecf20Sopenharmony_ci		list_del(&b->list);
31608c2ecf20Sopenharmony_ci		kfree(b);
31618c2ecf20Sopenharmony_ci	}
31628c2ecf20Sopenharmony_ci}
31638c2ecf20Sopenharmony_ci
31648c2ecf20Sopenharmony_ciint hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type)
31658c2ecf20Sopenharmony_ci{
31668c2ecf20Sopenharmony_ci	struct bdaddr_list *entry;
31678c2ecf20Sopenharmony_ci
31688c2ecf20Sopenharmony_ci	if (!bacmp(bdaddr, BDADDR_ANY))
31698c2ecf20Sopenharmony_ci		return -EBADF;
31708c2ecf20Sopenharmony_ci
31718c2ecf20Sopenharmony_ci	if (hci_bdaddr_list_lookup(list, bdaddr, type))
31728c2ecf20Sopenharmony_ci		return -EEXIST;
31738c2ecf20Sopenharmony_ci
31748c2ecf20Sopenharmony_ci	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
31758c2ecf20Sopenharmony_ci	if (!entry)
31768c2ecf20Sopenharmony_ci		return -ENOMEM;
31778c2ecf20Sopenharmony_ci
31788c2ecf20Sopenharmony_ci	bacpy(&entry->bdaddr, bdaddr);
31798c2ecf20Sopenharmony_ci	entry->bdaddr_type = type;
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_ci	list_add(&entry->list, list);
31828c2ecf20Sopenharmony_ci
31838c2ecf20Sopenharmony_ci	return 0;
31848c2ecf20Sopenharmony_ci}
31858c2ecf20Sopenharmony_ci
31868c2ecf20Sopenharmony_ciint hci_bdaddr_list_add_with_irk(struct list_head *list, bdaddr_t *bdaddr,
31878c2ecf20Sopenharmony_ci					u8 type, u8 *peer_irk, u8 *local_irk)
31888c2ecf20Sopenharmony_ci{
31898c2ecf20Sopenharmony_ci	struct bdaddr_list_with_irk *entry;
31908c2ecf20Sopenharmony_ci
31918c2ecf20Sopenharmony_ci	if (!bacmp(bdaddr, BDADDR_ANY))
31928c2ecf20Sopenharmony_ci		return -EBADF;
31938c2ecf20Sopenharmony_ci
31948c2ecf20Sopenharmony_ci	if (hci_bdaddr_list_lookup(list, bdaddr, type))
31958c2ecf20Sopenharmony_ci		return -EEXIST;
31968c2ecf20Sopenharmony_ci
31978c2ecf20Sopenharmony_ci	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
31988c2ecf20Sopenharmony_ci	if (!entry)
31998c2ecf20Sopenharmony_ci		return -ENOMEM;
32008c2ecf20Sopenharmony_ci
32018c2ecf20Sopenharmony_ci	bacpy(&entry->bdaddr, bdaddr);
32028c2ecf20Sopenharmony_ci	entry->bdaddr_type = type;
32038c2ecf20Sopenharmony_ci
32048c2ecf20Sopenharmony_ci	if (peer_irk)
32058c2ecf20Sopenharmony_ci		memcpy(entry->peer_irk, peer_irk, 16);
32068c2ecf20Sopenharmony_ci
32078c2ecf20Sopenharmony_ci	if (local_irk)
32088c2ecf20Sopenharmony_ci		memcpy(entry->local_irk, local_irk, 16);
32098c2ecf20Sopenharmony_ci
32108c2ecf20Sopenharmony_ci	list_add(&entry->list, list);
32118c2ecf20Sopenharmony_ci
32128c2ecf20Sopenharmony_ci	return 0;
32138c2ecf20Sopenharmony_ci}
32148c2ecf20Sopenharmony_ci
32158c2ecf20Sopenharmony_ciint hci_bdaddr_list_add_with_flags(struct list_head *list, bdaddr_t *bdaddr,
32168c2ecf20Sopenharmony_ci				   u8 type, u32 flags)
32178c2ecf20Sopenharmony_ci{
32188c2ecf20Sopenharmony_ci	struct bdaddr_list_with_flags *entry;
32198c2ecf20Sopenharmony_ci
32208c2ecf20Sopenharmony_ci	if (!bacmp(bdaddr, BDADDR_ANY))
32218c2ecf20Sopenharmony_ci		return -EBADF;
32228c2ecf20Sopenharmony_ci
32238c2ecf20Sopenharmony_ci	if (hci_bdaddr_list_lookup(list, bdaddr, type))
32248c2ecf20Sopenharmony_ci		return -EEXIST;
32258c2ecf20Sopenharmony_ci
32268c2ecf20Sopenharmony_ci	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
32278c2ecf20Sopenharmony_ci	if (!entry)
32288c2ecf20Sopenharmony_ci		return -ENOMEM;
32298c2ecf20Sopenharmony_ci
32308c2ecf20Sopenharmony_ci	bacpy(&entry->bdaddr, bdaddr);
32318c2ecf20Sopenharmony_ci	entry->bdaddr_type = type;
32328c2ecf20Sopenharmony_ci	entry->current_flags = flags;
32338c2ecf20Sopenharmony_ci
32348c2ecf20Sopenharmony_ci	list_add(&entry->list, list);
32358c2ecf20Sopenharmony_ci
32368c2ecf20Sopenharmony_ci	return 0;
32378c2ecf20Sopenharmony_ci}
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ciint hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type)
32408c2ecf20Sopenharmony_ci{
32418c2ecf20Sopenharmony_ci	struct bdaddr_list *entry;
32428c2ecf20Sopenharmony_ci
32438c2ecf20Sopenharmony_ci	if (!bacmp(bdaddr, BDADDR_ANY)) {
32448c2ecf20Sopenharmony_ci		hci_bdaddr_list_clear(list);
32458c2ecf20Sopenharmony_ci		return 0;
32468c2ecf20Sopenharmony_ci	}
32478c2ecf20Sopenharmony_ci
32488c2ecf20Sopenharmony_ci	entry = hci_bdaddr_list_lookup(list, bdaddr, type);
32498c2ecf20Sopenharmony_ci	if (!entry)
32508c2ecf20Sopenharmony_ci		return -ENOENT;
32518c2ecf20Sopenharmony_ci
32528c2ecf20Sopenharmony_ci	list_del(&entry->list);
32538c2ecf20Sopenharmony_ci	kfree(entry);
32548c2ecf20Sopenharmony_ci
32558c2ecf20Sopenharmony_ci	return 0;
32568c2ecf20Sopenharmony_ci}
32578c2ecf20Sopenharmony_ci
32588c2ecf20Sopenharmony_ciint hci_bdaddr_list_del_with_irk(struct list_head *list, bdaddr_t *bdaddr,
32598c2ecf20Sopenharmony_ci							u8 type)
32608c2ecf20Sopenharmony_ci{
32618c2ecf20Sopenharmony_ci	struct bdaddr_list_with_irk *entry;
32628c2ecf20Sopenharmony_ci
32638c2ecf20Sopenharmony_ci	if (!bacmp(bdaddr, BDADDR_ANY)) {
32648c2ecf20Sopenharmony_ci		hci_bdaddr_list_clear(list);
32658c2ecf20Sopenharmony_ci		return 0;
32668c2ecf20Sopenharmony_ci	}
32678c2ecf20Sopenharmony_ci
32688c2ecf20Sopenharmony_ci	entry = hci_bdaddr_list_lookup_with_irk(list, bdaddr, type);
32698c2ecf20Sopenharmony_ci	if (!entry)
32708c2ecf20Sopenharmony_ci		return -ENOENT;
32718c2ecf20Sopenharmony_ci
32728c2ecf20Sopenharmony_ci	list_del(&entry->list);
32738c2ecf20Sopenharmony_ci	kfree(entry);
32748c2ecf20Sopenharmony_ci
32758c2ecf20Sopenharmony_ci	return 0;
32768c2ecf20Sopenharmony_ci}
32778c2ecf20Sopenharmony_ci
32788c2ecf20Sopenharmony_ciint hci_bdaddr_list_del_with_flags(struct list_head *list, bdaddr_t *bdaddr,
32798c2ecf20Sopenharmony_ci				   u8 type)
32808c2ecf20Sopenharmony_ci{
32818c2ecf20Sopenharmony_ci	struct bdaddr_list_with_flags *entry;
32828c2ecf20Sopenharmony_ci
32838c2ecf20Sopenharmony_ci	if (!bacmp(bdaddr, BDADDR_ANY)) {
32848c2ecf20Sopenharmony_ci		hci_bdaddr_list_clear(list);
32858c2ecf20Sopenharmony_ci		return 0;
32868c2ecf20Sopenharmony_ci	}
32878c2ecf20Sopenharmony_ci
32888c2ecf20Sopenharmony_ci	entry = hci_bdaddr_list_lookup_with_flags(list, bdaddr, type);
32898c2ecf20Sopenharmony_ci	if (!entry)
32908c2ecf20Sopenharmony_ci		return -ENOENT;
32918c2ecf20Sopenharmony_ci
32928c2ecf20Sopenharmony_ci	list_del(&entry->list);
32938c2ecf20Sopenharmony_ci	kfree(entry);
32948c2ecf20Sopenharmony_ci
32958c2ecf20Sopenharmony_ci	return 0;
32968c2ecf20Sopenharmony_ci}
32978c2ecf20Sopenharmony_ci
32988c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
32998c2ecf20Sopenharmony_cistruct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
33008c2ecf20Sopenharmony_ci					       bdaddr_t *addr, u8 addr_type)
33018c2ecf20Sopenharmony_ci{
33028c2ecf20Sopenharmony_ci	struct hci_conn_params *params;
33038c2ecf20Sopenharmony_ci
33048c2ecf20Sopenharmony_ci	list_for_each_entry(params, &hdev->le_conn_params, list) {
33058c2ecf20Sopenharmony_ci		if (bacmp(&params->addr, addr) == 0 &&
33068c2ecf20Sopenharmony_ci		    params->addr_type == addr_type) {
33078c2ecf20Sopenharmony_ci			return params;
33088c2ecf20Sopenharmony_ci		}
33098c2ecf20Sopenharmony_ci	}
33108c2ecf20Sopenharmony_ci
33118c2ecf20Sopenharmony_ci	return NULL;
33128c2ecf20Sopenharmony_ci}
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
33158c2ecf20Sopenharmony_cistruct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
33168c2ecf20Sopenharmony_ci						  bdaddr_t *addr, u8 addr_type)
33178c2ecf20Sopenharmony_ci{
33188c2ecf20Sopenharmony_ci	struct hci_conn_params *param;
33198c2ecf20Sopenharmony_ci
33208c2ecf20Sopenharmony_ci	switch (addr_type) {
33218c2ecf20Sopenharmony_ci	case ADDR_LE_DEV_PUBLIC_RESOLVED:
33228c2ecf20Sopenharmony_ci		addr_type = ADDR_LE_DEV_PUBLIC;
33238c2ecf20Sopenharmony_ci		break;
33248c2ecf20Sopenharmony_ci	case ADDR_LE_DEV_RANDOM_RESOLVED:
33258c2ecf20Sopenharmony_ci		addr_type = ADDR_LE_DEV_RANDOM;
33268c2ecf20Sopenharmony_ci		break;
33278c2ecf20Sopenharmony_ci	}
33288c2ecf20Sopenharmony_ci
33298c2ecf20Sopenharmony_ci	list_for_each_entry(param, list, action) {
33308c2ecf20Sopenharmony_ci		if (bacmp(&param->addr, addr) == 0 &&
33318c2ecf20Sopenharmony_ci		    param->addr_type == addr_type)
33328c2ecf20Sopenharmony_ci			return param;
33338c2ecf20Sopenharmony_ci	}
33348c2ecf20Sopenharmony_ci
33358c2ecf20Sopenharmony_ci	return NULL;
33368c2ecf20Sopenharmony_ci}
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
33398c2ecf20Sopenharmony_cistruct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
33408c2ecf20Sopenharmony_ci					    bdaddr_t *addr, u8 addr_type)
33418c2ecf20Sopenharmony_ci{
33428c2ecf20Sopenharmony_ci	struct hci_conn_params *params;
33438c2ecf20Sopenharmony_ci
33448c2ecf20Sopenharmony_ci	params = hci_conn_params_lookup(hdev, addr, addr_type);
33458c2ecf20Sopenharmony_ci	if (params)
33468c2ecf20Sopenharmony_ci		return params;
33478c2ecf20Sopenharmony_ci
33488c2ecf20Sopenharmony_ci	params = kzalloc(sizeof(*params), GFP_KERNEL);
33498c2ecf20Sopenharmony_ci	if (!params) {
33508c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "out of memory");
33518c2ecf20Sopenharmony_ci		return NULL;
33528c2ecf20Sopenharmony_ci	}
33538c2ecf20Sopenharmony_ci
33548c2ecf20Sopenharmony_ci	bacpy(&params->addr, addr);
33558c2ecf20Sopenharmony_ci	params->addr_type = addr_type;
33568c2ecf20Sopenharmony_ci
33578c2ecf20Sopenharmony_ci	list_add(&params->list, &hdev->le_conn_params);
33588c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&params->action);
33598c2ecf20Sopenharmony_ci
33608c2ecf20Sopenharmony_ci	params->conn_min_interval = hdev->le_conn_min_interval;
33618c2ecf20Sopenharmony_ci	params->conn_max_interval = hdev->le_conn_max_interval;
33628c2ecf20Sopenharmony_ci	params->conn_latency = hdev->le_conn_latency;
33638c2ecf20Sopenharmony_ci	params->supervision_timeout = hdev->le_supv_timeout;
33648c2ecf20Sopenharmony_ci	params->auto_connect = HCI_AUTO_CONN_DISABLED;
33658c2ecf20Sopenharmony_ci
33668c2ecf20Sopenharmony_ci	BT_DBG("addr %pMR (type %u)", addr, addr_type);
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci	return params;
33698c2ecf20Sopenharmony_ci}
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_cistatic void hci_conn_params_free(struct hci_conn_params *params)
33728c2ecf20Sopenharmony_ci{
33738c2ecf20Sopenharmony_ci	if (params->conn) {
33748c2ecf20Sopenharmony_ci		hci_conn_drop(params->conn);
33758c2ecf20Sopenharmony_ci		hci_conn_put(params->conn);
33768c2ecf20Sopenharmony_ci	}
33778c2ecf20Sopenharmony_ci
33788c2ecf20Sopenharmony_ci	list_del(&params->action);
33798c2ecf20Sopenharmony_ci	list_del(&params->list);
33808c2ecf20Sopenharmony_ci	kfree(params);
33818c2ecf20Sopenharmony_ci}
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
33848c2ecf20Sopenharmony_civoid hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
33858c2ecf20Sopenharmony_ci{
33868c2ecf20Sopenharmony_ci	struct hci_conn_params *params;
33878c2ecf20Sopenharmony_ci
33888c2ecf20Sopenharmony_ci	params = hci_conn_params_lookup(hdev, addr, addr_type);
33898c2ecf20Sopenharmony_ci	if (!params)
33908c2ecf20Sopenharmony_ci		return;
33918c2ecf20Sopenharmony_ci
33928c2ecf20Sopenharmony_ci	hci_conn_params_free(params);
33938c2ecf20Sopenharmony_ci
33948c2ecf20Sopenharmony_ci	hci_update_background_scan(hdev);
33958c2ecf20Sopenharmony_ci
33968c2ecf20Sopenharmony_ci	BT_DBG("addr %pMR (type %u)", addr, addr_type);
33978c2ecf20Sopenharmony_ci}
33988c2ecf20Sopenharmony_ci
33998c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
34008c2ecf20Sopenharmony_civoid hci_conn_params_clear_disabled(struct hci_dev *hdev)
34018c2ecf20Sopenharmony_ci{
34028c2ecf20Sopenharmony_ci	struct hci_conn_params *params, *tmp;
34038c2ecf20Sopenharmony_ci
34048c2ecf20Sopenharmony_ci	list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
34058c2ecf20Sopenharmony_ci		if (params->auto_connect != HCI_AUTO_CONN_DISABLED)
34068c2ecf20Sopenharmony_ci			continue;
34078c2ecf20Sopenharmony_ci
34088c2ecf20Sopenharmony_ci		/* If trying to estabilish one time connection to disabled
34098c2ecf20Sopenharmony_ci		 * device, leave the params, but mark them as just once.
34108c2ecf20Sopenharmony_ci		 */
34118c2ecf20Sopenharmony_ci		if (params->explicit_connect) {
34128c2ecf20Sopenharmony_ci			params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
34138c2ecf20Sopenharmony_ci			continue;
34148c2ecf20Sopenharmony_ci		}
34158c2ecf20Sopenharmony_ci
34168c2ecf20Sopenharmony_ci		list_del(&params->list);
34178c2ecf20Sopenharmony_ci		kfree(params);
34188c2ecf20Sopenharmony_ci	}
34198c2ecf20Sopenharmony_ci
34208c2ecf20Sopenharmony_ci	BT_DBG("All LE disabled connection parameters were removed");
34218c2ecf20Sopenharmony_ci}
34228c2ecf20Sopenharmony_ci
34238c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */
34248c2ecf20Sopenharmony_cistatic void hci_conn_params_clear_all(struct hci_dev *hdev)
34258c2ecf20Sopenharmony_ci{
34268c2ecf20Sopenharmony_ci	struct hci_conn_params *params, *tmp;
34278c2ecf20Sopenharmony_ci
34288c2ecf20Sopenharmony_ci	list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list)
34298c2ecf20Sopenharmony_ci		hci_conn_params_free(params);
34308c2ecf20Sopenharmony_ci
34318c2ecf20Sopenharmony_ci	BT_DBG("All LE connection parameters were removed");
34328c2ecf20Sopenharmony_ci}
34338c2ecf20Sopenharmony_ci
34348c2ecf20Sopenharmony_ci/* Copy the Identity Address of the controller.
34358c2ecf20Sopenharmony_ci *
34368c2ecf20Sopenharmony_ci * If the controller has a public BD_ADDR, then by default use that one.
34378c2ecf20Sopenharmony_ci * If this is a LE only controller without a public address, default to
34388c2ecf20Sopenharmony_ci * the static random address.
34398c2ecf20Sopenharmony_ci *
34408c2ecf20Sopenharmony_ci * For debugging purposes it is possible to force controllers with a
34418c2ecf20Sopenharmony_ci * public address to use the static random address instead.
34428c2ecf20Sopenharmony_ci *
34438c2ecf20Sopenharmony_ci * In case BR/EDR has been disabled on a dual-mode controller and
34448c2ecf20Sopenharmony_ci * userspace has configured a static address, then that address
34458c2ecf20Sopenharmony_ci * becomes the identity address instead of the public BR/EDR address.
34468c2ecf20Sopenharmony_ci */
34478c2ecf20Sopenharmony_civoid hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
34488c2ecf20Sopenharmony_ci			       u8 *bdaddr_type)
34498c2ecf20Sopenharmony_ci{
34508c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
34518c2ecf20Sopenharmony_ci	    !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
34528c2ecf20Sopenharmony_ci	    (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
34538c2ecf20Sopenharmony_ci	     bacmp(&hdev->static_addr, BDADDR_ANY))) {
34548c2ecf20Sopenharmony_ci		bacpy(bdaddr, &hdev->static_addr);
34558c2ecf20Sopenharmony_ci		*bdaddr_type = ADDR_LE_DEV_RANDOM;
34568c2ecf20Sopenharmony_ci	} else {
34578c2ecf20Sopenharmony_ci		bacpy(bdaddr, &hdev->bdaddr);
34588c2ecf20Sopenharmony_ci		*bdaddr_type = ADDR_LE_DEV_PUBLIC;
34598c2ecf20Sopenharmony_ci	}
34608c2ecf20Sopenharmony_ci}
34618c2ecf20Sopenharmony_ci
34628c2ecf20Sopenharmony_cistatic void hci_suspend_clear_tasks(struct hci_dev *hdev)
34638c2ecf20Sopenharmony_ci{
34648c2ecf20Sopenharmony_ci	int i;
34658c2ecf20Sopenharmony_ci
34668c2ecf20Sopenharmony_ci	for (i = 0; i < __SUSPEND_NUM_TASKS; i++)
34678c2ecf20Sopenharmony_ci		clear_bit(i, hdev->suspend_tasks);
34688c2ecf20Sopenharmony_ci
34698c2ecf20Sopenharmony_ci	wake_up(&hdev->suspend_wait_q);
34708c2ecf20Sopenharmony_ci}
34718c2ecf20Sopenharmony_ci
34728c2ecf20Sopenharmony_cistatic int hci_suspend_wait_event(struct hci_dev *hdev)
34738c2ecf20Sopenharmony_ci{
34748c2ecf20Sopenharmony_ci#define WAKE_COND                                                              \
34758c2ecf20Sopenharmony_ci	(find_first_bit(hdev->suspend_tasks, __SUSPEND_NUM_TASKS) ==           \
34768c2ecf20Sopenharmony_ci	 __SUSPEND_NUM_TASKS)
34778c2ecf20Sopenharmony_ci
34788c2ecf20Sopenharmony_ci	int i;
34798c2ecf20Sopenharmony_ci	int ret = wait_event_timeout(hdev->suspend_wait_q,
34808c2ecf20Sopenharmony_ci				     WAKE_COND, SUSPEND_NOTIFIER_TIMEOUT);
34818c2ecf20Sopenharmony_ci
34828c2ecf20Sopenharmony_ci	if (ret == 0) {
34838c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "Timed out waiting for suspend events");
34848c2ecf20Sopenharmony_ci		for (i = 0; i < __SUSPEND_NUM_TASKS; ++i) {
34858c2ecf20Sopenharmony_ci			if (test_bit(i, hdev->suspend_tasks))
34868c2ecf20Sopenharmony_ci				bt_dev_err(hdev, "Suspend timeout bit: %d", i);
34878c2ecf20Sopenharmony_ci			clear_bit(i, hdev->suspend_tasks);
34888c2ecf20Sopenharmony_ci		}
34898c2ecf20Sopenharmony_ci
34908c2ecf20Sopenharmony_ci		ret = -ETIMEDOUT;
34918c2ecf20Sopenharmony_ci	} else {
34928c2ecf20Sopenharmony_ci		ret = 0;
34938c2ecf20Sopenharmony_ci	}
34948c2ecf20Sopenharmony_ci
34958c2ecf20Sopenharmony_ci	return ret;
34968c2ecf20Sopenharmony_ci}
34978c2ecf20Sopenharmony_ci
34988c2ecf20Sopenharmony_cistatic void hci_prepare_suspend(struct work_struct *work)
34998c2ecf20Sopenharmony_ci{
35008c2ecf20Sopenharmony_ci	struct hci_dev *hdev =
35018c2ecf20Sopenharmony_ci		container_of(work, struct hci_dev, suspend_prepare);
35028c2ecf20Sopenharmony_ci
35038c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
35048c2ecf20Sopenharmony_ci	hci_req_prepare_suspend(hdev, hdev->suspend_state_next);
35058c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
35068c2ecf20Sopenharmony_ci}
35078c2ecf20Sopenharmony_ci
35088c2ecf20Sopenharmony_cistatic int hci_change_suspend_state(struct hci_dev *hdev,
35098c2ecf20Sopenharmony_ci				    enum suspended_state next)
35108c2ecf20Sopenharmony_ci{
35118c2ecf20Sopenharmony_ci	hdev->suspend_state_next = next;
35128c2ecf20Sopenharmony_ci	set_bit(SUSPEND_PREPARE_NOTIFIER, hdev->suspend_tasks);
35138c2ecf20Sopenharmony_ci	queue_work(hdev->req_workqueue, &hdev->suspend_prepare);
35148c2ecf20Sopenharmony_ci	return hci_suspend_wait_event(hdev);
35158c2ecf20Sopenharmony_ci}
35168c2ecf20Sopenharmony_ci
35178c2ecf20Sopenharmony_cistatic void hci_clear_wake_reason(struct hci_dev *hdev)
35188c2ecf20Sopenharmony_ci{
35198c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
35208c2ecf20Sopenharmony_ci
35218c2ecf20Sopenharmony_ci	hdev->wake_reason = 0;
35228c2ecf20Sopenharmony_ci	bacpy(&hdev->wake_addr, BDADDR_ANY);
35238c2ecf20Sopenharmony_ci	hdev->wake_addr_type = 0;
35248c2ecf20Sopenharmony_ci
35258c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
35268c2ecf20Sopenharmony_ci}
35278c2ecf20Sopenharmony_ci
35288c2ecf20Sopenharmony_cistatic int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
35298c2ecf20Sopenharmony_ci				void *data)
35308c2ecf20Sopenharmony_ci{
35318c2ecf20Sopenharmony_ci	struct hci_dev *hdev =
35328c2ecf20Sopenharmony_ci		container_of(nb, struct hci_dev, suspend_notifier);
35338c2ecf20Sopenharmony_ci	int ret = 0;
35348c2ecf20Sopenharmony_ci	u8 state = BT_RUNNING;
35358c2ecf20Sopenharmony_ci
35368c2ecf20Sopenharmony_ci	/* If powering down, wait for completion. */
35378c2ecf20Sopenharmony_ci	if (mgmt_powering_down(hdev)) {
35388c2ecf20Sopenharmony_ci		set_bit(SUSPEND_POWERING_DOWN, hdev->suspend_tasks);
35398c2ecf20Sopenharmony_ci		ret = hci_suspend_wait_event(hdev);
35408c2ecf20Sopenharmony_ci		if (ret)
35418c2ecf20Sopenharmony_ci			goto done;
35428c2ecf20Sopenharmony_ci	}
35438c2ecf20Sopenharmony_ci
35448c2ecf20Sopenharmony_ci	/* Suspend notifier should only act on events when powered. */
35458c2ecf20Sopenharmony_ci	if (!hdev_is_powered(hdev) ||
35468c2ecf20Sopenharmony_ci	    hci_dev_test_flag(hdev, HCI_UNREGISTER))
35478c2ecf20Sopenharmony_ci		goto done;
35488c2ecf20Sopenharmony_ci
35498c2ecf20Sopenharmony_ci	if (action == PM_SUSPEND_PREPARE) {
35508c2ecf20Sopenharmony_ci		/* Suspend consists of two actions:
35518c2ecf20Sopenharmony_ci		 *  - First, disconnect everything and make the controller not
35528c2ecf20Sopenharmony_ci		 *    connectable (disabling scanning)
35538c2ecf20Sopenharmony_ci		 *  - Second, program event filter/accept list and enable scan
35548c2ecf20Sopenharmony_ci		 */
35558c2ecf20Sopenharmony_ci		ret = hci_change_suspend_state(hdev, BT_SUSPEND_DISCONNECT);
35568c2ecf20Sopenharmony_ci		if (!ret)
35578c2ecf20Sopenharmony_ci			state = BT_SUSPEND_DISCONNECT;
35588c2ecf20Sopenharmony_ci
35598c2ecf20Sopenharmony_ci		/* Only configure accept list if disconnect succeeded and wake
35608c2ecf20Sopenharmony_ci		 * isn't being prevented.
35618c2ecf20Sopenharmony_ci		 */
35628c2ecf20Sopenharmony_ci		if (!ret && !(hdev->prevent_wake && hdev->prevent_wake(hdev))) {
35638c2ecf20Sopenharmony_ci			ret = hci_change_suspend_state(hdev,
35648c2ecf20Sopenharmony_ci						BT_SUSPEND_CONFIGURE_WAKE);
35658c2ecf20Sopenharmony_ci			if (!ret)
35668c2ecf20Sopenharmony_ci				state = BT_SUSPEND_CONFIGURE_WAKE;
35678c2ecf20Sopenharmony_ci		}
35688c2ecf20Sopenharmony_ci
35698c2ecf20Sopenharmony_ci		hci_clear_wake_reason(hdev);
35708c2ecf20Sopenharmony_ci		mgmt_suspending(hdev, state);
35718c2ecf20Sopenharmony_ci
35728c2ecf20Sopenharmony_ci	} else if (action == PM_POST_SUSPEND) {
35738c2ecf20Sopenharmony_ci		ret = hci_change_suspend_state(hdev, BT_RUNNING);
35748c2ecf20Sopenharmony_ci
35758c2ecf20Sopenharmony_ci		mgmt_resuming(hdev, hdev->wake_reason, &hdev->wake_addr,
35768c2ecf20Sopenharmony_ci			      hdev->wake_addr_type);
35778c2ecf20Sopenharmony_ci	}
35788c2ecf20Sopenharmony_ci
35798c2ecf20Sopenharmony_cidone:
35808c2ecf20Sopenharmony_ci	/* We always allow suspend even if suspend preparation failed and
35818c2ecf20Sopenharmony_ci	 * attempt to recover in resume.
35828c2ecf20Sopenharmony_ci	 */
35838c2ecf20Sopenharmony_ci	if (ret)
35848c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d",
35858c2ecf20Sopenharmony_ci			   action, ret);
35868c2ecf20Sopenharmony_ci
35878c2ecf20Sopenharmony_ci	return NOTIFY_DONE;
35888c2ecf20Sopenharmony_ci}
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_ci/* Alloc HCI device */
35918c2ecf20Sopenharmony_cistruct hci_dev *hci_alloc_dev(void)
35928c2ecf20Sopenharmony_ci{
35938c2ecf20Sopenharmony_ci	struct hci_dev *hdev;
35948c2ecf20Sopenharmony_ci
35958c2ecf20Sopenharmony_ci	hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
35968c2ecf20Sopenharmony_ci	if (!hdev)
35978c2ecf20Sopenharmony_ci		return NULL;
35988c2ecf20Sopenharmony_ci
35998c2ecf20Sopenharmony_ci	hdev->pkt_type  = (HCI_DM1 | HCI_DH1 | HCI_HV1);
36008c2ecf20Sopenharmony_ci	hdev->esco_type = (ESCO_HV1);
36018c2ecf20Sopenharmony_ci	hdev->link_mode = (HCI_LM_ACCEPT);
36028c2ecf20Sopenharmony_ci	hdev->num_iac = 0x01;		/* One IAC support is mandatory */
36038c2ecf20Sopenharmony_ci	hdev->io_capability = 0x03;	/* No Input No Output */
36048c2ecf20Sopenharmony_ci	hdev->manufacturer = 0xffff;	/* Default to internal use */
36058c2ecf20Sopenharmony_ci	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
36068c2ecf20Sopenharmony_ci	hdev->adv_tx_power = HCI_TX_POWER_INVALID;
36078c2ecf20Sopenharmony_ci	hdev->adv_instance_cnt = 0;
36088c2ecf20Sopenharmony_ci	hdev->cur_adv_instance = 0x00;
36098c2ecf20Sopenharmony_ci	hdev->adv_instance_timeout = 0;
36108c2ecf20Sopenharmony_ci
36118c2ecf20Sopenharmony_ci	hdev->advmon_allowlist_duration = 300;
36128c2ecf20Sopenharmony_ci	hdev->advmon_no_filter_duration = 500;
36138c2ecf20Sopenharmony_ci
36148c2ecf20Sopenharmony_ci	hdev->sniff_max_interval = 800;
36158c2ecf20Sopenharmony_ci	hdev->sniff_min_interval = 80;
36168c2ecf20Sopenharmony_ci
36178c2ecf20Sopenharmony_ci	hdev->le_adv_channel_map = 0x07;
36188c2ecf20Sopenharmony_ci	hdev->le_adv_min_interval = 0x0800;
36198c2ecf20Sopenharmony_ci	hdev->le_adv_max_interval = 0x0800;
36208c2ecf20Sopenharmony_ci	hdev->le_scan_interval = 0x0060;
36218c2ecf20Sopenharmony_ci	hdev->le_scan_window = 0x0030;
36228c2ecf20Sopenharmony_ci	hdev->le_scan_int_suspend = 0x0400;
36238c2ecf20Sopenharmony_ci	hdev->le_scan_window_suspend = 0x0012;
36248c2ecf20Sopenharmony_ci	hdev->le_scan_int_discovery = DISCOV_LE_SCAN_INT;
36258c2ecf20Sopenharmony_ci	hdev->le_scan_window_discovery = DISCOV_LE_SCAN_WIN;
36268c2ecf20Sopenharmony_ci	hdev->le_scan_int_connect = 0x0060;
36278c2ecf20Sopenharmony_ci	hdev->le_scan_window_connect = 0x0060;
36288c2ecf20Sopenharmony_ci	hdev->le_conn_min_interval = 0x0018;
36298c2ecf20Sopenharmony_ci	hdev->le_conn_max_interval = 0x0028;
36308c2ecf20Sopenharmony_ci	hdev->le_conn_latency = 0x0000;
36318c2ecf20Sopenharmony_ci	hdev->le_supv_timeout = 0x002a;
36328c2ecf20Sopenharmony_ci	hdev->le_def_tx_len = 0x001b;
36338c2ecf20Sopenharmony_ci	hdev->le_def_tx_time = 0x0148;
36348c2ecf20Sopenharmony_ci	hdev->le_max_tx_len = 0x001b;
36358c2ecf20Sopenharmony_ci	hdev->le_max_tx_time = 0x0148;
36368c2ecf20Sopenharmony_ci	hdev->le_max_rx_len = 0x001b;
36378c2ecf20Sopenharmony_ci	hdev->le_max_rx_time = 0x0148;
36388c2ecf20Sopenharmony_ci	hdev->le_max_key_size = SMP_MAX_ENC_KEY_SIZE;
36398c2ecf20Sopenharmony_ci	hdev->le_min_key_size = SMP_MIN_ENC_KEY_SIZE;
36408c2ecf20Sopenharmony_ci	hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M;
36418c2ecf20Sopenharmony_ci	hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M;
36428c2ecf20Sopenharmony_ci	hdev->le_num_of_adv_sets = HCI_MAX_ADV_INSTANCES;
36438c2ecf20Sopenharmony_ci	hdev->def_multi_adv_rotation_duration = HCI_DEFAULT_ADV_DURATION;
36448c2ecf20Sopenharmony_ci	hdev->def_le_autoconnect_timeout = HCI_LE_AUTOCONN_TIMEOUT;
36458c2ecf20Sopenharmony_ci
36468c2ecf20Sopenharmony_ci	hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT;
36478c2ecf20Sopenharmony_ci	hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT;
36488c2ecf20Sopenharmony_ci	hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE;
36498c2ecf20Sopenharmony_ci	hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE;
36508c2ecf20Sopenharmony_ci	hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT;
36518c2ecf20Sopenharmony_ci	hdev->min_enc_key_size = HCI_MIN_ENC_KEY_SIZE;
36528c2ecf20Sopenharmony_ci
36538c2ecf20Sopenharmony_ci	/* default 1.28 sec page scan */
36548c2ecf20Sopenharmony_ci	hdev->def_page_scan_type = PAGE_SCAN_TYPE_STANDARD;
36558c2ecf20Sopenharmony_ci	hdev->def_page_scan_int = 0x0800;
36568c2ecf20Sopenharmony_ci	hdev->def_page_scan_window = 0x0012;
36578c2ecf20Sopenharmony_ci
36588c2ecf20Sopenharmony_ci	mutex_init(&hdev->lock);
36598c2ecf20Sopenharmony_ci	mutex_init(&hdev->req_lock);
36608c2ecf20Sopenharmony_ci
36618c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->mgmt_pending);
36628c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->reject_list);
36638c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->accept_list);
36648c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->uuids);
36658c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->link_keys);
36668c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->long_term_keys);
36678c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->identity_resolving_keys);
36688c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->remote_oob_data);
36698c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->le_accept_list);
36708c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->le_resolv_list);
36718c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->le_conn_params);
36728c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->pend_le_conns);
36738c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->pend_le_reports);
36748c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->conn_hash.list);
36758c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->adv_instances);
36768c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdev->blocked_keys);
36778c2ecf20Sopenharmony_ci
36788c2ecf20Sopenharmony_ci	INIT_WORK(&hdev->rx_work, hci_rx_work);
36798c2ecf20Sopenharmony_ci	INIT_WORK(&hdev->cmd_work, hci_cmd_work);
36808c2ecf20Sopenharmony_ci	INIT_WORK(&hdev->tx_work, hci_tx_work);
36818c2ecf20Sopenharmony_ci	INIT_WORK(&hdev->power_on, hci_power_on);
36828c2ecf20Sopenharmony_ci	INIT_WORK(&hdev->error_reset, hci_error_reset);
36838c2ecf20Sopenharmony_ci	INIT_WORK(&hdev->suspend_prepare, hci_prepare_suspend);
36848c2ecf20Sopenharmony_ci
36858c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
36868c2ecf20Sopenharmony_ci
36878c2ecf20Sopenharmony_ci	skb_queue_head_init(&hdev->rx_q);
36888c2ecf20Sopenharmony_ci	skb_queue_head_init(&hdev->cmd_q);
36898c2ecf20Sopenharmony_ci	skb_queue_head_init(&hdev->raw_q);
36908c2ecf20Sopenharmony_ci
36918c2ecf20Sopenharmony_ci	init_waitqueue_head(&hdev->req_wait_q);
36928c2ecf20Sopenharmony_ci	init_waitqueue_head(&hdev->suspend_wait_q);
36938c2ecf20Sopenharmony_ci
36948c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&hdev->cmd_timer, hci_cmd_timeout);
36958c2ecf20Sopenharmony_ci
36968c2ecf20Sopenharmony_ci	hci_request_setup(hdev);
36978c2ecf20Sopenharmony_ci
36988c2ecf20Sopenharmony_ci	hci_init_sysfs(hdev);
36998c2ecf20Sopenharmony_ci	discovery_init(hdev);
37008c2ecf20Sopenharmony_ci
37018c2ecf20Sopenharmony_ci	return hdev;
37028c2ecf20Sopenharmony_ci}
37038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_alloc_dev);
37048c2ecf20Sopenharmony_ci
37058c2ecf20Sopenharmony_ci/* Free HCI device */
37068c2ecf20Sopenharmony_civoid hci_free_dev(struct hci_dev *hdev)
37078c2ecf20Sopenharmony_ci{
37088c2ecf20Sopenharmony_ci	/* will free via device release */
37098c2ecf20Sopenharmony_ci	put_device(&hdev->dev);
37108c2ecf20Sopenharmony_ci}
37118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_free_dev);
37128c2ecf20Sopenharmony_ci
37138c2ecf20Sopenharmony_ci/* Register HCI device */
37148c2ecf20Sopenharmony_ciint hci_register_dev(struct hci_dev *hdev)
37158c2ecf20Sopenharmony_ci{
37168c2ecf20Sopenharmony_ci	int id, error;
37178c2ecf20Sopenharmony_ci
37188c2ecf20Sopenharmony_ci	if (!hdev->open || !hdev->close || !hdev->send)
37198c2ecf20Sopenharmony_ci		return -EINVAL;
37208c2ecf20Sopenharmony_ci
37218c2ecf20Sopenharmony_ci	/* Do not allow HCI_AMP devices to register at index 0,
37228c2ecf20Sopenharmony_ci	 * so the index can be used as the AMP controller ID.
37238c2ecf20Sopenharmony_ci	 */
37248c2ecf20Sopenharmony_ci	switch (hdev->dev_type) {
37258c2ecf20Sopenharmony_ci	case HCI_PRIMARY:
37268c2ecf20Sopenharmony_ci		id = ida_simple_get(&hci_index_ida, 0, HCI_MAX_ID, GFP_KERNEL);
37278c2ecf20Sopenharmony_ci		break;
37288c2ecf20Sopenharmony_ci	case HCI_AMP:
37298c2ecf20Sopenharmony_ci		id = ida_simple_get(&hci_index_ida, 1, HCI_MAX_ID, GFP_KERNEL);
37308c2ecf20Sopenharmony_ci		break;
37318c2ecf20Sopenharmony_ci	default:
37328c2ecf20Sopenharmony_ci		return -EINVAL;
37338c2ecf20Sopenharmony_ci	}
37348c2ecf20Sopenharmony_ci
37358c2ecf20Sopenharmony_ci	if (id < 0)
37368c2ecf20Sopenharmony_ci		return id;
37378c2ecf20Sopenharmony_ci
37388c2ecf20Sopenharmony_ci	error = dev_set_name(&hdev->dev, "hci%u", id);
37398c2ecf20Sopenharmony_ci	if (error)
37408c2ecf20Sopenharmony_ci		return error;
37418c2ecf20Sopenharmony_ci
37428c2ecf20Sopenharmony_ci	hdev->name = dev_name(&hdev->dev);
37438c2ecf20Sopenharmony_ci	hdev->id = id;
37448c2ecf20Sopenharmony_ci
37458c2ecf20Sopenharmony_ci	BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
37468c2ecf20Sopenharmony_ci
37478c2ecf20Sopenharmony_ci	hdev->workqueue = alloc_ordered_workqueue("%s", WQ_HIGHPRI, hdev->name);
37488c2ecf20Sopenharmony_ci	if (!hdev->workqueue) {
37498c2ecf20Sopenharmony_ci		error = -ENOMEM;
37508c2ecf20Sopenharmony_ci		goto err;
37518c2ecf20Sopenharmony_ci	}
37528c2ecf20Sopenharmony_ci
37538c2ecf20Sopenharmony_ci	hdev->req_workqueue = alloc_ordered_workqueue("%s", WQ_HIGHPRI,
37548c2ecf20Sopenharmony_ci						      hdev->name);
37558c2ecf20Sopenharmony_ci	if (!hdev->req_workqueue) {
37568c2ecf20Sopenharmony_ci		destroy_workqueue(hdev->workqueue);
37578c2ecf20Sopenharmony_ci		error = -ENOMEM;
37588c2ecf20Sopenharmony_ci		goto err;
37598c2ecf20Sopenharmony_ci	}
37608c2ecf20Sopenharmony_ci
37618c2ecf20Sopenharmony_ci	if (!IS_ERR_OR_NULL(bt_debugfs))
37628c2ecf20Sopenharmony_ci		hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs);
37638c2ecf20Sopenharmony_ci
37648c2ecf20Sopenharmony_ci	error = device_add(&hdev->dev);
37658c2ecf20Sopenharmony_ci	if (error < 0)
37668c2ecf20Sopenharmony_ci		goto err_wqueue;
37678c2ecf20Sopenharmony_ci
37688c2ecf20Sopenharmony_ci	hci_leds_init(hdev);
37698c2ecf20Sopenharmony_ci
37708c2ecf20Sopenharmony_ci	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
37718c2ecf20Sopenharmony_ci				    RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops,
37728c2ecf20Sopenharmony_ci				    hdev);
37738c2ecf20Sopenharmony_ci	if (hdev->rfkill) {
37748c2ecf20Sopenharmony_ci		if (rfkill_register(hdev->rfkill) < 0) {
37758c2ecf20Sopenharmony_ci			rfkill_destroy(hdev->rfkill);
37768c2ecf20Sopenharmony_ci			hdev->rfkill = NULL;
37778c2ecf20Sopenharmony_ci		}
37788c2ecf20Sopenharmony_ci	}
37798c2ecf20Sopenharmony_ci
37808c2ecf20Sopenharmony_ci	if (hdev->rfkill && rfkill_blocked(hdev->rfkill))
37818c2ecf20Sopenharmony_ci		hci_dev_set_flag(hdev, HCI_RFKILLED);
37828c2ecf20Sopenharmony_ci
37838c2ecf20Sopenharmony_ci	hci_dev_set_flag(hdev, HCI_SETUP);
37848c2ecf20Sopenharmony_ci	hci_dev_set_flag(hdev, HCI_AUTO_OFF);
37858c2ecf20Sopenharmony_ci
37868c2ecf20Sopenharmony_ci	if (hdev->dev_type == HCI_PRIMARY) {
37878c2ecf20Sopenharmony_ci		/* Assume BR/EDR support until proven otherwise (such as
37888c2ecf20Sopenharmony_ci		 * through reading supported features during init.
37898c2ecf20Sopenharmony_ci		 */
37908c2ecf20Sopenharmony_ci		hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
37918c2ecf20Sopenharmony_ci	}
37928c2ecf20Sopenharmony_ci
37938c2ecf20Sopenharmony_ci	write_lock(&hci_dev_list_lock);
37948c2ecf20Sopenharmony_ci	list_add(&hdev->list, &hci_dev_list);
37958c2ecf20Sopenharmony_ci	write_unlock(&hci_dev_list_lock);
37968c2ecf20Sopenharmony_ci
37978c2ecf20Sopenharmony_ci	/* Devices that are marked for raw-only usage are unconfigured
37988c2ecf20Sopenharmony_ci	 * and should not be included in normal operation.
37998c2ecf20Sopenharmony_ci	 */
38008c2ecf20Sopenharmony_ci	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
38018c2ecf20Sopenharmony_ci		hci_dev_set_flag(hdev, HCI_UNCONFIGURED);
38028c2ecf20Sopenharmony_ci
38038c2ecf20Sopenharmony_ci	hci_sock_dev_event(hdev, HCI_DEV_REG);
38048c2ecf20Sopenharmony_ci	hci_dev_hold(hdev);
38058c2ecf20Sopenharmony_ci
38068c2ecf20Sopenharmony_ci	if (!hdev->suspend_notifier.notifier_call &&
38078c2ecf20Sopenharmony_ci	    !test_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks)) {
38088c2ecf20Sopenharmony_ci		hdev->suspend_notifier.notifier_call = hci_suspend_notifier;
38098c2ecf20Sopenharmony_ci		error = register_pm_notifier(&hdev->suspend_notifier);
38108c2ecf20Sopenharmony_ci		if (error)
38118c2ecf20Sopenharmony_ci			goto err_wqueue;
38128c2ecf20Sopenharmony_ci	}
38138c2ecf20Sopenharmony_ci
38148c2ecf20Sopenharmony_ci	queue_work(hdev->req_workqueue, &hdev->power_on);
38158c2ecf20Sopenharmony_ci
38168c2ecf20Sopenharmony_ci	idr_init(&hdev->adv_monitors_idr);
38178c2ecf20Sopenharmony_ci
38188c2ecf20Sopenharmony_ci	return id;
38198c2ecf20Sopenharmony_ci
38208c2ecf20Sopenharmony_cierr_wqueue:
38218c2ecf20Sopenharmony_ci	debugfs_remove_recursive(hdev->debugfs);
38228c2ecf20Sopenharmony_ci	destroy_workqueue(hdev->workqueue);
38238c2ecf20Sopenharmony_ci	destroy_workqueue(hdev->req_workqueue);
38248c2ecf20Sopenharmony_cierr:
38258c2ecf20Sopenharmony_ci	ida_simple_remove(&hci_index_ida, hdev->id);
38268c2ecf20Sopenharmony_ci
38278c2ecf20Sopenharmony_ci	return error;
38288c2ecf20Sopenharmony_ci}
38298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_register_dev);
38308c2ecf20Sopenharmony_ci
38318c2ecf20Sopenharmony_ci/* Unregister HCI device */
38328c2ecf20Sopenharmony_civoid hci_unregister_dev(struct hci_dev *hdev)
38338c2ecf20Sopenharmony_ci{
38348c2ecf20Sopenharmony_ci	BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
38358c2ecf20Sopenharmony_ci
38368c2ecf20Sopenharmony_ci	hci_dev_set_flag(hdev, HCI_UNREGISTER);
38378c2ecf20Sopenharmony_ci
38388c2ecf20Sopenharmony_ci	write_lock(&hci_dev_list_lock);
38398c2ecf20Sopenharmony_ci	list_del(&hdev->list);
38408c2ecf20Sopenharmony_ci	write_unlock(&hci_dev_list_lock);
38418c2ecf20Sopenharmony_ci
38428c2ecf20Sopenharmony_ci	cancel_work_sync(&hdev->rx_work);
38438c2ecf20Sopenharmony_ci	cancel_work_sync(&hdev->cmd_work);
38448c2ecf20Sopenharmony_ci	cancel_work_sync(&hdev->tx_work);
38458c2ecf20Sopenharmony_ci	cancel_work_sync(&hdev->power_on);
38468c2ecf20Sopenharmony_ci	cancel_work_sync(&hdev->error_reset);
38478c2ecf20Sopenharmony_ci
38488c2ecf20Sopenharmony_ci	if (!test_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks)) {
38498c2ecf20Sopenharmony_ci		hci_suspend_clear_tasks(hdev);
38508c2ecf20Sopenharmony_ci		unregister_pm_notifier(&hdev->suspend_notifier);
38518c2ecf20Sopenharmony_ci		cancel_work_sync(&hdev->suspend_prepare);
38528c2ecf20Sopenharmony_ci	}
38538c2ecf20Sopenharmony_ci
38548c2ecf20Sopenharmony_ci	hci_dev_do_close(hdev);
38558c2ecf20Sopenharmony_ci
38568c2ecf20Sopenharmony_ci	if (!test_bit(HCI_INIT, &hdev->flags) &&
38578c2ecf20Sopenharmony_ci	    !hci_dev_test_flag(hdev, HCI_SETUP) &&
38588c2ecf20Sopenharmony_ci	    !hci_dev_test_flag(hdev, HCI_CONFIG)) {
38598c2ecf20Sopenharmony_ci		hci_dev_lock(hdev);
38608c2ecf20Sopenharmony_ci		mgmt_index_removed(hdev);
38618c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
38628c2ecf20Sopenharmony_ci	}
38638c2ecf20Sopenharmony_ci
38648c2ecf20Sopenharmony_ci	/* mgmt_index_removed should take care of emptying the
38658c2ecf20Sopenharmony_ci	 * pending list */
38668c2ecf20Sopenharmony_ci	BUG_ON(!list_empty(&hdev->mgmt_pending));
38678c2ecf20Sopenharmony_ci
38688c2ecf20Sopenharmony_ci	hci_sock_dev_event(hdev, HCI_DEV_UNREG);
38698c2ecf20Sopenharmony_ci
38708c2ecf20Sopenharmony_ci	if (hdev->rfkill) {
38718c2ecf20Sopenharmony_ci		rfkill_unregister(hdev->rfkill);
38728c2ecf20Sopenharmony_ci		rfkill_destroy(hdev->rfkill);
38738c2ecf20Sopenharmony_ci	}
38748c2ecf20Sopenharmony_ci
38758c2ecf20Sopenharmony_ci	device_del(&hdev->dev);
38768c2ecf20Sopenharmony_ci	/* Actual cleanup is deferred until hci_cleanup_dev(). */
38778c2ecf20Sopenharmony_ci	hci_dev_put(hdev);
38788c2ecf20Sopenharmony_ci}
38798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_unregister_dev);
38808c2ecf20Sopenharmony_ci
38818c2ecf20Sopenharmony_ci/* Cleanup HCI device */
38828c2ecf20Sopenharmony_civoid hci_cleanup_dev(struct hci_dev *hdev)
38838c2ecf20Sopenharmony_ci{
38848c2ecf20Sopenharmony_ci	debugfs_remove_recursive(hdev->debugfs);
38858c2ecf20Sopenharmony_ci	kfree_const(hdev->hw_info);
38868c2ecf20Sopenharmony_ci	kfree_const(hdev->fw_info);
38878c2ecf20Sopenharmony_ci
38888c2ecf20Sopenharmony_ci	destroy_workqueue(hdev->workqueue);
38898c2ecf20Sopenharmony_ci	destroy_workqueue(hdev->req_workqueue);
38908c2ecf20Sopenharmony_ci
38918c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
38928c2ecf20Sopenharmony_ci	hci_bdaddr_list_clear(&hdev->reject_list);
38938c2ecf20Sopenharmony_ci	hci_bdaddr_list_clear(&hdev->accept_list);
38948c2ecf20Sopenharmony_ci	hci_uuids_clear(hdev);
38958c2ecf20Sopenharmony_ci	hci_link_keys_clear(hdev);
38968c2ecf20Sopenharmony_ci	hci_smp_ltks_clear(hdev);
38978c2ecf20Sopenharmony_ci	hci_smp_irks_clear(hdev);
38988c2ecf20Sopenharmony_ci	hci_remote_oob_data_clear(hdev);
38998c2ecf20Sopenharmony_ci	hci_adv_instances_clear(hdev);
39008c2ecf20Sopenharmony_ci	hci_adv_monitors_clear(hdev);
39018c2ecf20Sopenharmony_ci	hci_bdaddr_list_clear(&hdev->le_accept_list);
39028c2ecf20Sopenharmony_ci	hci_bdaddr_list_clear(&hdev->le_resolv_list);
39038c2ecf20Sopenharmony_ci	hci_conn_params_clear_all(hdev);
39048c2ecf20Sopenharmony_ci	hci_discovery_filter_clear(hdev);
39058c2ecf20Sopenharmony_ci	hci_blocked_keys_clear(hdev);
39068c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
39078c2ecf20Sopenharmony_ci
39088c2ecf20Sopenharmony_ci	ida_simple_remove(&hci_index_ida, hdev->id);
39098c2ecf20Sopenharmony_ci}
39108c2ecf20Sopenharmony_ci
39118c2ecf20Sopenharmony_ci/* Suspend HCI device */
39128c2ecf20Sopenharmony_ciint hci_suspend_dev(struct hci_dev *hdev)
39138c2ecf20Sopenharmony_ci{
39148c2ecf20Sopenharmony_ci	hci_sock_dev_event(hdev, HCI_DEV_SUSPEND);
39158c2ecf20Sopenharmony_ci	return 0;
39168c2ecf20Sopenharmony_ci}
39178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_suspend_dev);
39188c2ecf20Sopenharmony_ci
39198c2ecf20Sopenharmony_ci/* Resume HCI device */
39208c2ecf20Sopenharmony_ciint hci_resume_dev(struct hci_dev *hdev)
39218c2ecf20Sopenharmony_ci{
39228c2ecf20Sopenharmony_ci	hci_sock_dev_event(hdev, HCI_DEV_RESUME);
39238c2ecf20Sopenharmony_ci	return 0;
39248c2ecf20Sopenharmony_ci}
39258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_resume_dev);
39268c2ecf20Sopenharmony_ci
39278c2ecf20Sopenharmony_ci/* Reset HCI device */
39288c2ecf20Sopenharmony_ciint hci_reset_dev(struct hci_dev *hdev)
39298c2ecf20Sopenharmony_ci{
39308c2ecf20Sopenharmony_ci	static const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 };
39318c2ecf20Sopenharmony_ci	struct sk_buff *skb;
39328c2ecf20Sopenharmony_ci
39338c2ecf20Sopenharmony_ci	skb = bt_skb_alloc(3, GFP_ATOMIC);
39348c2ecf20Sopenharmony_ci	if (!skb)
39358c2ecf20Sopenharmony_ci		return -ENOMEM;
39368c2ecf20Sopenharmony_ci
39378c2ecf20Sopenharmony_ci	hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
39388c2ecf20Sopenharmony_ci	skb_put_data(skb, hw_err, 3);
39398c2ecf20Sopenharmony_ci
39408c2ecf20Sopenharmony_ci	/* Send Hardware Error to upper stack */
39418c2ecf20Sopenharmony_ci	return hci_recv_frame(hdev, skb);
39428c2ecf20Sopenharmony_ci}
39438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_reset_dev);
39448c2ecf20Sopenharmony_ci
39458c2ecf20Sopenharmony_ci/* Receive frame from HCI drivers */
39468c2ecf20Sopenharmony_ciint hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
39478c2ecf20Sopenharmony_ci{
39488c2ecf20Sopenharmony_ci	if (!hdev || (!test_bit(HCI_UP, &hdev->flags)
39498c2ecf20Sopenharmony_ci		      && !test_bit(HCI_INIT, &hdev->flags))) {
39508c2ecf20Sopenharmony_ci		kfree_skb(skb);
39518c2ecf20Sopenharmony_ci		return -ENXIO;
39528c2ecf20Sopenharmony_ci	}
39538c2ecf20Sopenharmony_ci
39548c2ecf20Sopenharmony_ci	if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
39558c2ecf20Sopenharmony_ci	    hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
39568c2ecf20Sopenharmony_ci	    hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
39578c2ecf20Sopenharmony_ci	    hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) {
39588c2ecf20Sopenharmony_ci		kfree_skb(skb);
39598c2ecf20Sopenharmony_ci		return -EINVAL;
39608c2ecf20Sopenharmony_ci	}
39618c2ecf20Sopenharmony_ci
39628c2ecf20Sopenharmony_ci	/* Incoming skb */
39638c2ecf20Sopenharmony_ci	bt_cb(skb)->incoming = 1;
39648c2ecf20Sopenharmony_ci
39658c2ecf20Sopenharmony_ci	/* Time stamp */
39668c2ecf20Sopenharmony_ci	__net_timestamp(skb);
39678c2ecf20Sopenharmony_ci
39688c2ecf20Sopenharmony_ci	skb_queue_tail(&hdev->rx_q, skb);
39698c2ecf20Sopenharmony_ci	queue_work(hdev->workqueue, &hdev->rx_work);
39708c2ecf20Sopenharmony_ci
39718c2ecf20Sopenharmony_ci	return 0;
39728c2ecf20Sopenharmony_ci}
39738c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_recv_frame);
39748c2ecf20Sopenharmony_ci
39758c2ecf20Sopenharmony_ci/* Receive diagnostic message from HCI drivers */
39768c2ecf20Sopenharmony_ciint hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb)
39778c2ecf20Sopenharmony_ci{
39788c2ecf20Sopenharmony_ci	/* Mark as diagnostic packet */
39798c2ecf20Sopenharmony_ci	hci_skb_pkt_type(skb) = HCI_DIAG_PKT;
39808c2ecf20Sopenharmony_ci
39818c2ecf20Sopenharmony_ci	/* Time stamp */
39828c2ecf20Sopenharmony_ci	__net_timestamp(skb);
39838c2ecf20Sopenharmony_ci
39848c2ecf20Sopenharmony_ci	skb_queue_tail(&hdev->rx_q, skb);
39858c2ecf20Sopenharmony_ci	queue_work(hdev->workqueue, &hdev->rx_work);
39868c2ecf20Sopenharmony_ci
39878c2ecf20Sopenharmony_ci	return 0;
39888c2ecf20Sopenharmony_ci}
39898c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_recv_diag);
39908c2ecf20Sopenharmony_ci
39918c2ecf20Sopenharmony_civoid hci_set_hw_info(struct hci_dev *hdev, const char *fmt, ...)
39928c2ecf20Sopenharmony_ci{
39938c2ecf20Sopenharmony_ci	va_list vargs;
39948c2ecf20Sopenharmony_ci
39958c2ecf20Sopenharmony_ci	va_start(vargs, fmt);
39968c2ecf20Sopenharmony_ci	kfree_const(hdev->hw_info);
39978c2ecf20Sopenharmony_ci	hdev->hw_info = kvasprintf_const(GFP_KERNEL, fmt, vargs);
39988c2ecf20Sopenharmony_ci	va_end(vargs);
39998c2ecf20Sopenharmony_ci}
40008c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_set_hw_info);
40018c2ecf20Sopenharmony_ci
40028c2ecf20Sopenharmony_civoid hci_set_fw_info(struct hci_dev *hdev, const char *fmt, ...)
40038c2ecf20Sopenharmony_ci{
40048c2ecf20Sopenharmony_ci	va_list vargs;
40058c2ecf20Sopenharmony_ci
40068c2ecf20Sopenharmony_ci	va_start(vargs, fmt);
40078c2ecf20Sopenharmony_ci	kfree_const(hdev->fw_info);
40088c2ecf20Sopenharmony_ci	hdev->fw_info = kvasprintf_const(GFP_KERNEL, fmt, vargs);
40098c2ecf20Sopenharmony_ci	va_end(vargs);
40108c2ecf20Sopenharmony_ci}
40118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_set_fw_info);
40128c2ecf20Sopenharmony_ci
40138c2ecf20Sopenharmony_ci/* ---- Interface to upper protocols ---- */
40148c2ecf20Sopenharmony_ci
40158c2ecf20Sopenharmony_ciint hci_register_cb(struct hci_cb *cb)
40168c2ecf20Sopenharmony_ci{
40178c2ecf20Sopenharmony_ci	BT_DBG("%p name %s", cb, cb->name);
40188c2ecf20Sopenharmony_ci
40198c2ecf20Sopenharmony_ci	mutex_lock(&hci_cb_list_lock);
40208c2ecf20Sopenharmony_ci	list_add_tail(&cb->list, &hci_cb_list);
40218c2ecf20Sopenharmony_ci	mutex_unlock(&hci_cb_list_lock);
40228c2ecf20Sopenharmony_ci
40238c2ecf20Sopenharmony_ci	return 0;
40248c2ecf20Sopenharmony_ci}
40258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_register_cb);
40268c2ecf20Sopenharmony_ci
40278c2ecf20Sopenharmony_ciint hci_unregister_cb(struct hci_cb *cb)
40288c2ecf20Sopenharmony_ci{
40298c2ecf20Sopenharmony_ci	BT_DBG("%p name %s", cb, cb->name);
40308c2ecf20Sopenharmony_ci
40318c2ecf20Sopenharmony_ci	mutex_lock(&hci_cb_list_lock);
40328c2ecf20Sopenharmony_ci	list_del(&cb->list);
40338c2ecf20Sopenharmony_ci	mutex_unlock(&hci_cb_list_lock);
40348c2ecf20Sopenharmony_ci
40358c2ecf20Sopenharmony_ci	return 0;
40368c2ecf20Sopenharmony_ci}
40378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_unregister_cb);
40388c2ecf20Sopenharmony_ci
40398c2ecf20Sopenharmony_cistatic void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
40408c2ecf20Sopenharmony_ci{
40418c2ecf20Sopenharmony_ci	int err;
40428c2ecf20Sopenharmony_ci
40438c2ecf20Sopenharmony_ci	BT_DBG("%s type %d len %d", hdev->name, hci_skb_pkt_type(skb),
40448c2ecf20Sopenharmony_ci	       skb->len);
40458c2ecf20Sopenharmony_ci
40468c2ecf20Sopenharmony_ci	/* Time stamp */
40478c2ecf20Sopenharmony_ci	__net_timestamp(skb);
40488c2ecf20Sopenharmony_ci
40498c2ecf20Sopenharmony_ci	/* Send copy to monitor */
40508c2ecf20Sopenharmony_ci	hci_send_to_monitor(hdev, skb);
40518c2ecf20Sopenharmony_ci
40528c2ecf20Sopenharmony_ci	if (atomic_read(&hdev->promisc)) {
40538c2ecf20Sopenharmony_ci		/* Send copy to the sockets */
40548c2ecf20Sopenharmony_ci		hci_send_to_sock(hdev, skb);
40558c2ecf20Sopenharmony_ci	}
40568c2ecf20Sopenharmony_ci
40578c2ecf20Sopenharmony_ci	/* Get rid of skb owner, prior to sending to the driver. */
40588c2ecf20Sopenharmony_ci	skb_orphan(skb);
40598c2ecf20Sopenharmony_ci
40608c2ecf20Sopenharmony_ci	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
40618c2ecf20Sopenharmony_ci		kfree_skb(skb);
40628c2ecf20Sopenharmony_ci		return;
40638c2ecf20Sopenharmony_ci	}
40648c2ecf20Sopenharmony_ci
40658c2ecf20Sopenharmony_ci	err = hdev->send(hdev, skb);
40668c2ecf20Sopenharmony_ci	if (err < 0) {
40678c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "sending frame failed (%d)", err);
40688c2ecf20Sopenharmony_ci		kfree_skb(skb);
40698c2ecf20Sopenharmony_ci	}
40708c2ecf20Sopenharmony_ci}
40718c2ecf20Sopenharmony_ci
40728c2ecf20Sopenharmony_ci/* Send HCI command */
40738c2ecf20Sopenharmony_ciint hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen,
40748c2ecf20Sopenharmony_ci		 const void *param)
40758c2ecf20Sopenharmony_ci{
40768c2ecf20Sopenharmony_ci	struct sk_buff *skb;
40778c2ecf20Sopenharmony_ci
40788c2ecf20Sopenharmony_ci	BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen);
40798c2ecf20Sopenharmony_ci
40808c2ecf20Sopenharmony_ci	skb = hci_prepare_cmd(hdev, opcode, plen, param);
40818c2ecf20Sopenharmony_ci	if (!skb) {
40828c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "no memory for command");
40838c2ecf20Sopenharmony_ci		return -ENOMEM;
40848c2ecf20Sopenharmony_ci	}
40858c2ecf20Sopenharmony_ci
40868c2ecf20Sopenharmony_ci	/* Stand-alone HCI commands must be flagged as
40878c2ecf20Sopenharmony_ci	 * single-command requests.
40888c2ecf20Sopenharmony_ci	 */
40898c2ecf20Sopenharmony_ci	bt_cb(skb)->hci.req_flags |= HCI_REQ_START;
40908c2ecf20Sopenharmony_ci
40918c2ecf20Sopenharmony_ci	skb_queue_tail(&hdev->cmd_q, skb);
40928c2ecf20Sopenharmony_ci	queue_work(hdev->workqueue, &hdev->cmd_work);
40938c2ecf20Sopenharmony_ci
40948c2ecf20Sopenharmony_ci	return 0;
40958c2ecf20Sopenharmony_ci}
40968c2ecf20Sopenharmony_ci
40978c2ecf20Sopenharmony_ciint __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen,
40988c2ecf20Sopenharmony_ci		   const void *param)
40998c2ecf20Sopenharmony_ci{
41008c2ecf20Sopenharmony_ci	struct sk_buff *skb;
41018c2ecf20Sopenharmony_ci
41028c2ecf20Sopenharmony_ci	if (hci_opcode_ogf(opcode) != 0x3f) {
41038c2ecf20Sopenharmony_ci		/* A controller receiving a command shall respond with either
41048c2ecf20Sopenharmony_ci		 * a Command Status Event or a Command Complete Event.
41058c2ecf20Sopenharmony_ci		 * Therefore, all standard HCI commands must be sent via the
41068c2ecf20Sopenharmony_ci		 * standard API, using hci_send_cmd or hci_cmd_sync helpers.
41078c2ecf20Sopenharmony_ci		 * Some vendors do not comply with this rule for vendor-specific
41088c2ecf20Sopenharmony_ci		 * commands and do not return any event. We want to support
41098c2ecf20Sopenharmony_ci		 * unresponded commands for such cases only.
41108c2ecf20Sopenharmony_ci		 */
41118c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "unresponded command not supported");
41128c2ecf20Sopenharmony_ci		return -EINVAL;
41138c2ecf20Sopenharmony_ci	}
41148c2ecf20Sopenharmony_ci
41158c2ecf20Sopenharmony_ci	skb = hci_prepare_cmd(hdev, opcode, plen, param);
41168c2ecf20Sopenharmony_ci	if (!skb) {
41178c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "no memory for command (opcode 0x%4.4x)",
41188c2ecf20Sopenharmony_ci			   opcode);
41198c2ecf20Sopenharmony_ci		return -ENOMEM;
41208c2ecf20Sopenharmony_ci	}
41218c2ecf20Sopenharmony_ci
41228c2ecf20Sopenharmony_ci	hci_send_frame(hdev, skb);
41238c2ecf20Sopenharmony_ci
41248c2ecf20Sopenharmony_ci	return 0;
41258c2ecf20Sopenharmony_ci}
41268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__hci_cmd_send);
41278c2ecf20Sopenharmony_ci
41288c2ecf20Sopenharmony_ci/* Get data from the previously sent command */
41298c2ecf20Sopenharmony_civoid *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
41308c2ecf20Sopenharmony_ci{
41318c2ecf20Sopenharmony_ci	struct hci_command_hdr *hdr;
41328c2ecf20Sopenharmony_ci
41338c2ecf20Sopenharmony_ci	if (!hdev->sent_cmd)
41348c2ecf20Sopenharmony_ci		return NULL;
41358c2ecf20Sopenharmony_ci
41368c2ecf20Sopenharmony_ci	hdr = (void *) hdev->sent_cmd->data;
41378c2ecf20Sopenharmony_ci
41388c2ecf20Sopenharmony_ci	if (hdr->opcode != cpu_to_le16(opcode))
41398c2ecf20Sopenharmony_ci		return NULL;
41408c2ecf20Sopenharmony_ci
41418c2ecf20Sopenharmony_ci	BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
41428c2ecf20Sopenharmony_ci
41438c2ecf20Sopenharmony_ci	return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE;
41448c2ecf20Sopenharmony_ci}
41458c2ecf20Sopenharmony_ci
41468c2ecf20Sopenharmony_ci/* Send HCI command and wait for command commplete event */
41478c2ecf20Sopenharmony_cistruct sk_buff *hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
41488c2ecf20Sopenharmony_ci			     const void *param, u32 timeout)
41498c2ecf20Sopenharmony_ci{
41508c2ecf20Sopenharmony_ci	struct sk_buff *skb;
41518c2ecf20Sopenharmony_ci
41528c2ecf20Sopenharmony_ci	if (!test_bit(HCI_UP, &hdev->flags))
41538c2ecf20Sopenharmony_ci		return ERR_PTR(-ENETDOWN);
41548c2ecf20Sopenharmony_ci
41558c2ecf20Sopenharmony_ci	bt_dev_dbg(hdev, "opcode 0x%4.4x plen %d", opcode, plen);
41568c2ecf20Sopenharmony_ci
41578c2ecf20Sopenharmony_ci	hci_req_sync_lock(hdev);
41588c2ecf20Sopenharmony_ci	skb = __hci_cmd_sync(hdev, opcode, plen, param, timeout);
41598c2ecf20Sopenharmony_ci	hci_req_sync_unlock(hdev);
41608c2ecf20Sopenharmony_ci
41618c2ecf20Sopenharmony_ci	return skb;
41628c2ecf20Sopenharmony_ci}
41638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_cmd_sync);
41648c2ecf20Sopenharmony_ci
41658c2ecf20Sopenharmony_ci/* Send ACL data */
41668c2ecf20Sopenharmony_cistatic void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
41678c2ecf20Sopenharmony_ci{
41688c2ecf20Sopenharmony_ci	struct hci_acl_hdr *hdr;
41698c2ecf20Sopenharmony_ci	int len = skb->len;
41708c2ecf20Sopenharmony_ci
41718c2ecf20Sopenharmony_ci	skb_push(skb, HCI_ACL_HDR_SIZE);
41728c2ecf20Sopenharmony_ci	skb_reset_transport_header(skb);
41738c2ecf20Sopenharmony_ci	hdr = (struct hci_acl_hdr *)skb_transport_header(skb);
41748c2ecf20Sopenharmony_ci	hdr->handle = cpu_to_le16(hci_handle_pack(handle, flags));
41758c2ecf20Sopenharmony_ci	hdr->dlen   = cpu_to_le16(len);
41768c2ecf20Sopenharmony_ci}
41778c2ecf20Sopenharmony_ci
41788c2ecf20Sopenharmony_cistatic void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,
41798c2ecf20Sopenharmony_ci			  struct sk_buff *skb, __u16 flags)
41808c2ecf20Sopenharmony_ci{
41818c2ecf20Sopenharmony_ci	struct hci_conn *conn = chan->conn;
41828c2ecf20Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
41838c2ecf20Sopenharmony_ci	struct sk_buff *list;
41848c2ecf20Sopenharmony_ci
41858c2ecf20Sopenharmony_ci	skb->len = skb_headlen(skb);
41868c2ecf20Sopenharmony_ci	skb->data_len = 0;
41878c2ecf20Sopenharmony_ci
41888c2ecf20Sopenharmony_ci	hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
41898c2ecf20Sopenharmony_ci
41908c2ecf20Sopenharmony_ci	switch (hdev->dev_type) {
41918c2ecf20Sopenharmony_ci	case HCI_PRIMARY:
41928c2ecf20Sopenharmony_ci		hci_add_acl_hdr(skb, conn->handle, flags);
41938c2ecf20Sopenharmony_ci		break;
41948c2ecf20Sopenharmony_ci	case HCI_AMP:
41958c2ecf20Sopenharmony_ci		hci_add_acl_hdr(skb, chan->handle, flags);
41968c2ecf20Sopenharmony_ci		break;
41978c2ecf20Sopenharmony_ci	default:
41988c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type);
41998c2ecf20Sopenharmony_ci		return;
42008c2ecf20Sopenharmony_ci	}
42018c2ecf20Sopenharmony_ci
42028c2ecf20Sopenharmony_ci	list = skb_shinfo(skb)->frag_list;
42038c2ecf20Sopenharmony_ci	if (!list) {
42048c2ecf20Sopenharmony_ci		/* Non fragmented */
42058c2ecf20Sopenharmony_ci		BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len);
42068c2ecf20Sopenharmony_ci
42078c2ecf20Sopenharmony_ci		skb_queue_tail(queue, skb);
42088c2ecf20Sopenharmony_ci	} else {
42098c2ecf20Sopenharmony_ci		/* Fragmented */
42108c2ecf20Sopenharmony_ci		BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
42118c2ecf20Sopenharmony_ci
42128c2ecf20Sopenharmony_ci		skb_shinfo(skb)->frag_list = NULL;
42138c2ecf20Sopenharmony_ci
42148c2ecf20Sopenharmony_ci		/* Queue all fragments atomically. We need to use spin_lock_bh
42158c2ecf20Sopenharmony_ci		 * here because of 6LoWPAN links, as there this function is
42168c2ecf20Sopenharmony_ci		 * called from softirq and using normal spin lock could cause
42178c2ecf20Sopenharmony_ci		 * deadlocks.
42188c2ecf20Sopenharmony_ci		 */
42198c2ecf20Sopenharmony_ci		spin_lock_bh(&queue->lock);
42208c2ecf20Sopenharmony_ci
42218c2ecf20Sopenharmony_ci		__skb_queue_tail(queue, skb);
42228c2ecf20Sopenharmony_ci
42238c2ecf20Sopenharmony_ci		flags &= ~ACL_START;
42248c2ecf20Sopenharmony_ci		flags |= ACL_CONT;
42258c2ecf20Sopenharmony_ci		do {
42268c2ecf20Sopenharmony_ci			skb = list; list = list->next;
42278c2ecf20Sopenharmony_ci
42288c2ecf20Sopenharmony_ci			hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
42298c2ecf20Sopenharmony_ci			hci_add_acl_hdr(skb, conn->handle, flags);
42308c2ecf20Sopenharmony_ci
42318c2ecf20Sopenharmony_ci			BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
42328c2ecf20Sopenharmony_ci
42338c2ecf20Sopenharmony_ci			__skb_queue_tail(queue, skb);
42348c2ecf20Sopenharmony_ci		} while (list);
42358c2ecf20Sopenharmony_ci
42368c2ecf20Sopenharmony_ci		spin_unlock_bh(&queue->lock);
42378c2ecf20Sopenharmony_ci	}
42388c2ecf20Sopenharmony_ci}
42398c2ecf20Sopenharmony_ci
42408c2ecf20Sopenharmony_civoid hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
42418c2ecf20Sopenharmony_ci{
42428c2ecf20Sopenharmony_ci	struct hci_dev *hdev = chan->conn->hdev;
42438c2ecf20Sopenharmony_ci
42448c2ecf20Sopenharmony_ci	BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags);
42458c2ecf20Sopenharmony_ci
42468c2ecf20Sopenharmony_ci	hci_queue_acl(chan, &chan->data_q, skb, flags);
42478c2ecf20Sopenharmony_ci
42488c2ecf20Sopenharmony_ci	queue_work(hdev->workqueue, &hdev->tx_work);
42498c2ecf20Sopenharmony_ci}
42508c2ecf20Sopenharmony_ci
42518c2ecf20Sopenharmony_ci/* Send SCO data */
42528c2ecf20Sopenharmony_civoid hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
42538c2ecf20Sopenharmony_ci{
42548c2ecf20Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
42558c2ecf20Sopenharmony_ci	struct hci_sco_hdr hdr;
42568c2ecf20Sopenharmony_ci
42578c2ecf20Sopenharmony_ci	BT_DBG("%s len %d", hdev->name, skb->len);
42588c2ecf20Sopenharmony_ci
42598c2ecf20Sopenharmony_ci	hdr.handle = cpu_to_le16(conn->handle);
42608c2ecf20Sopenharmony_ci	hdr.dlen   = skb->len;
42618c2ecf20Sopenharmony_ci
42628c2ecf20Sopenharmony_ci	skb_push(skb, HCI_SCO_HDR_SIZE);
42638c2ecf20Sopenharmony_ci	skb_reset_transport_header(skb);
42648c2ecf20Sopenharmony_ci	memcpy(skb_transport_header(skb), &hdr, HCI_SCO_HDR_SIZE);
42658c2ecf20Sopenharmony_ci
42668c2ecf20Sopenharmony_ci	hci_skb_pkt_type(skb) = HCI_SCODATA_PKT;
42678c2ecf20Sopenharmony_ci
42688c2ecf20Sopenharmony_ci	skb_queue_tail(&conn->data_q, skb);
42698c2ecf20Sopenharmony_ci	queue_work(hdev->workqueue, &hdev->tx_work);
42708c2ecf20Sopenharmony_ci}
42718c2ecf20Sopenharmony_ci
42728c2ecf20Sopenharmony_ci/* ---- HCI TX task (outgoing data) ---- */
42738c2ecf20Sopenharmony_ci
42748c2ecf20Sopenharmony_ci/* HCI Connection scheduler */
42758c2ecf20Sopenharmony_cistatic struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type,
42768c2ecf20Sopenharmony_ci				     int *quote)
42778c2ecf20Sopenharmony_ci{
42788c2ecf20Sopenharmony_ci	struct hci_conn_hash *h = &hdev->conn_hash;
42798c2ecf20Sopenharmony_ci	struct hci_conn *conn = NULL, *c;
42808c2ecf20Sopenharmony_ci	unsigned int num = 0, min = ~0;
42818c2ecf20Sopenharmony_ci
42828c2ecf20Sopenharmony_ci	/* We don't have to lock device here. Connections are always
42838c2ecf20Sopenharmony_ci	 * added and removed with TX task disabled. */
42848c2ecf20Sopenharmony_ci
42858c2ecf20Sopenharmony_ci	rcu_read_lock();
42868c2ecf20Sopenharmony_ci
42878c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(c, &h->list, list) {
42888c2ecf20Sopenharmony_ci		if (c->type != type || skb_queue_empty(&c->data_q))
42898c2ecf20Sopenharmony_ci			continue;
42908c2ecf20Sopenharmony_ci
42918c2ecf20Sopenharmony_ci		if (c->state != BT_CONNECTED && c->state != BT_CONFIG)
42928c2ecf20Sopenharmony_ci			continue;
42938c2ecf20Sopenharmony_ci
42948c2ecf20Sopenharmony_ci		num++;
42958c2ecf20Sopenharmony_ci
42968c2ecf20Sopenharmony_ci		if (c->sent < min) {
42978c2ecf20Sopenharmony_ci			min  = c->sent;
42988c2ecf20Sopenharmony_ci			conn = c;
42998c2ecf20Sopenharmony_ci		}
43008c2ecf20Sopenharmony_ci
43018c2ecf20Sopenharmony_ci		if (hci_conn_num(hdev, type) == num)
43028c2ecf20Sopenharmony_ci			break;
43038c2ecf20Sopenharmony_ci	}
43048c2ecf20Sopenharmony_ci
43058c2ecf20Sopenharmony_ci	rcu_read_unlock();
43068c2ecf20Sopenharmony_ci
43078c2ecf20Sopenharmony_ci	if (conn) {
43088c2ecf20Sopenharmony_ci		int cnt, q;
43098c2ecf20Sopenharmony_ci
43108c2ecf20Sopenharmony_ci		switch (conn->type) {
43118c2ecf20Sopenharmony_ci		case ACL_LINK:
43128c2ecf20Sopenharmony_ci			cnt = hdev->acl_cnt;
43138c2ecf20Sopenharmony_ci			break;
43148c2ecf20Sopenharmony_ci		case SCO_LINK:
43158c2ecf20Sopenharmony_ci		case ESCO_LINK:
43168c2ecf20Sopenharmony_ci			cnt = hdev->sco_cnt;
43178c2ecf20Sopenharmony_ci			break;
43188c2ecf20Sopenharmony_ci		case LE_LINK:
43198c2ecf20Sopenharmony_ci			cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
43208c2ecf20Sopenharmony_ci			break;
43218c2ecf20Sopenharmony_ci		default:
43228c2ecf20Sopenharmony_ci			cnt = 0;
43238c2ecf20Sopenharmony_ci			bt_dev_err(hdev, "unknown link type %d", conn->type);
43248c2ecf20Sopenharmony_ci		}
43258c2ecf20Sopenharmony_ci
43268c2ecf20Sopenharmony_ci		q = cnt / num;
43278c2ecf20Sopenharmony_ci		*quote = q ? q : 1;
43288c2ecf20Sopenharmony_ci	} else
43298c2ecf20Sopenharmony_ci		*quote = 0;
43308c2ecf20Sopenharmony_ci
43318c2ecf20Sopenharmony_ci	BT_DBG("conn %p quote %d", conn, *quote);
43328c2ecf20Sopenharmony_ci	return conn;
43338c2ecf20Sopenharmony_ci}
43348c2ecf20Sopenharmony_ci
43358c2ecf20Sopenharmony_cistatic void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
43368c2ecf20Sopenharmony_ci{
43378c2ecf20Sopenharmony_ci	struct hci_conn_hash *h = &hdev->conn_hash;
43388c2ecf20Sopenharmony_ci	struct hci_conn *c;
43398c2ecf20Sopenharmony_ci
43408c2ecf20Sopenharmony_ci	bt_dev_err(hdev, "link tx timeout");
43418c2ecf20Sopenharmony_ci
43428c2ecf20Sopenharmony_ci	rcu_read_lock();
43438c2ecf20Sopenharmony_ci
43448c2ecf20Sopenharmony_ci	/* Kill stalled connections */
43458c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(c, &h->list, list) {
43468c2ecf20Sopenharmony_ci		if (c->type == type && c->sent) {
43478c2ecf20Sopenharmony_ci			bt_dev_err(hdev, "killing stalled connection %pMR",
43488c2ecf20Sopenharmony_ci				   &c->dst);
43498c2ecf20Sopenharmony_ci			hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM);
43508c2ecf20Sopenharmony_ci		}
43518c2ecf20Sopenharmony_ci	}
43528c2ecf20Sopenharmony_ci
43538c2ecf20Sopenharmony_ci	rcu_read_unlock();
43548c2ecf20Sopenharmony_ci}
43558c2ecf20Sopenharmony_ci
43568c2ecf20Sopenharmony_cistatic struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
43578c2ecf20Sopenharmony_ci				      int *quote)
43588c2ecf20Sopenharmony_ci{
43598c2ecf20Sopenharmony_ci	struct hci_conn_hash *h = &hdev->conn_hash;
43608c2ecf20Sopenharmony_ci	struct hci_chan *chan = NULL;
43618c2ecf20Sopenharmony_ci	unsigned int num = 0, min = ~0, cur_prio = 0;
43628c2ecf20Sopenharmony_ci	struct hci_conn *conn;
43638c2ecf20Sopenharmony_ci	int cnt, q, conn_num = 0;
43648c2ecf20Sopenharmony_ci
43658c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
43668c2ecf20Sopenharmony_ci
43678c2ecf20Sopenharmony_ci	rcu_read_lock();
43688c2ecf20Sopenharmony_ci
43698c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(conn, &h->list, list) {
43708c2ecf20Sopenharmony_ci		struct hci_chan *tmp;
43718c2ecf20Sopenharmony_ci
43728c2ecf20Sopenharmony_ci		if (conn->type != type)
43738c2ecf20Sopenharmony_ci			continue;
43748c2ecf20Sopenharmony_ci
43758c2ecf20Sopenharmony_ci		if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
43768c2ecf20Sopenharmony_ci			continue;
43778c2ecf20Sopenharmony_ci
43788c2ecf20Sopenharmony_ci		conn_num++;
43798c2ecf20Sopenharmony_ci
43808c2ecf20Sopenharmony_ci		list_for_each_entry_rcu(tmp, &conn->chan_list, list) {
43818c2ecf20Sopenharmony_ci			struct sk_buff *skb;
43828c2ecf20Sopenharmony_ci
43838c2ecf20Sopenharmony_ci			if (skb_queue_empty(&tmp->data_q))
43848c2ecf20Sopenharmony_ci				continue;
43858c2ecf20Sopenharmony_ci
43868c2ecf20Sopenharmony_ci			skb = skb_peek(&tmp->data_q);
43878c2ecf20Sopenharmony_ci			if (skb->priority < cur_prio)
43888c2ecf20Sopenharmony_ci				continue;
43898c2ecf20Sopenharmony_ci
43908c2ecf20Sopenharmony_ci			if (skb->priority > cur_prio) {
43918c2ecf20Sopenharmony_ci				num = 0;
43928c2ecf20Sopenharmony_ci				min = ~0;
43938c2ecf20Sopenharmony_ci				cur_prio = skb->priority;
43948c2ecf20Sopenharmony_ci			}
43958c2ecf20Sopenharmony_ci
43968c2ecf20Sopenharmony_ci			num++;
43978c2ecf20Sopenharmony_ci
43988c2ecf20Sopenharmony_ci			if (conn->sent < min) {
43998c2ecf20Sopenharmony_ci				min  = conn->sent;
44008c2ecf20Sopenharmony_ci				chan = tmp;
44018c2ecf20Sopenharmony_ci			}
44028c2ecf20Sopenharmony_ci		}
44038c2ecf20Sopenharmony_ci
44048c2ecf20Sopenharmony_ci		if (hci_conn_num(hdev, type) == conn_num)
44058c2ecf20Sopenharmony_ci			break;
44068c2ecf20Sopenharmony_ci	}
44078c2ecf20Sopenharmony_ci
44088c2ecf20Sopenharmony_ci	rcu_read_unlock();
44098c2ecf20Sopenharmony_ci
44108c2ecf20Sopenharmony_ci	if (!chan)
44118c2ecf20Sopenharmony_ci		return NULL;
44128c2ecf20Sopenharmony_ci
44138c2ecf20Sopenharmony_ci	switch (chan->conn->type) {
44148c2ecf20Sopenharmony_ci	case ACL_LINK:
44158c2ecf20Sopenharmony_ci		cnt = hdev->acl_cnt;
44168c2ecf20Sopenharmony_ci		break;
44178c2ecf20Sopenharmony_ci	case AMP_LINK:
44188c2ecf20Sopenharmony_ci		cnt = hdev->block_cnt;
44198c2ecf20Sopenharmony_ci		break;
44208c2ecf20Sopenharmony_ci	case SCO_LINK:
44218c2ecf20Sopenharmony_ci	case ESCO_LINK:
44228c2ecf20Sopenharmony_ci		cnt = hdev->sco_cnt;
44238c2ecf20Sopenharmony_ci		break;
44248c2ecf20Sopenharmony_ci	case LE_LINK:
44258c2ecf20Sopenharmony_ci		cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
44268c2ecf20Sopenharmony_ci		break;
44278c2ecf20Sopenharmony_ci	default:
44288c2ecf20Sopenharmony_ci		cnt = 0;
44298c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "unknown link type %d", chan->conn->type);
44308c2ecf20Sopenharmony_ci	}
44318c2ecf20Sopenharmony_ci
44328c2ecf20Sopenharmony_ci	q = cnt / num;
44338c2ecf20Sopenharmony_ci	*quote = q ? q : 1;
44348c2ecf20Sopenharmony_ci	BT_DBG("chan %p quote %d", chan, *quote);
44358c2ecf20Sopenharmony_ci	return chan;
44368c2ecf20Sopenharmony_ci}
44378c2ecf20Sopenharmony_ci
44388c2ecf20Sopenharmony_cistatic void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
44398c2ecf20Sopenharmony_ci{
44408c2ecf20Sopenharmony_ci	struct hci_conn_hash *h = &hdev->conn_hash;
44418c2ecf20Sopenharmony_ci	struct hci_conn *conn;
44428c2ecf20Sopenharmony_ci	int num = 0;
44438c2ecf20Sopenharmony_ci
44448c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
44458c2ecf20Sopenharmony_ci
44468c2ecf20Sopenharmony_ci	rcu_read_lock();
44478c2ecf20Sopenharmony_ci
44488c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(conn, &h->list, list) {
44498c2ecf20Sopenharmony_ci		struct hci_chan *chan;
44508c2ecf20Sopenharmony_ci
44518c2ecf20Sopenharmony_ci		if (conn->type != type)
44528c2ecf20Sopenharmony_ci			continue;
44538c2ecf20Sopenharmony_ci
44548c2ecf20Sopenharmony_ci		if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
44558c2ecf20Sopenharmony_ci			continue;
44568c2ecf20Sopenharmony_ci
44578c2ecf20Sopenharmony_ci		num++;
44588c2ecf20Sopenharmony_ci
44598c2ecf20Sopenharmony_ci		list_for_each_entry_rcu(chan, &conn->chan_list, list) {
44608c2ecf20Sopenharmony_ci			struct sk_buff *skb;
44618c2ecf20Sopenharmony_ci
44628c2ecf20Sopenharmony_ci			if (chan->sent) {
44638c2ecf20Sopenharmony_ci				chan->sent = 0;
44648c2ecf20Sopenharmony_ci				continue;
44658c2ecf20Sopenharmony_ci			}
44668c2ecf20Sopenharmony_ci
44678c2ecf20Sopenharmony_ci			if (skb_queue_empty(&chan->data_q))
44688c2ecf20Sopenharmony_ci				continue;
44698c2ecf20Sopenharmony_ci
44708c2ecf20Sopenharmony_ci			skb = skb_peek(&chan->data_q);
44718c2ecf20Sopenharmony_ci			if (skb->priority >= HCI_PRIO_MAX - 1)
44728c2ecf20Sopenharmony_ci				continue;
44738c2ecf20Sopenharmony_ci
44748c2ecf20Sopenharmony_ci			skb->priority = HCI_PRIO_MAX - 1;
44758c2ecf20Sopenharmony_ci
44768c2ecf20Sopenharmony_ci			BT_DBG("chan %p skb %p promoted to %d", chan, skb,
44778c2ecf20Sopenharmony_ci			       skb->priority);
44788c2ecf20Sopenharmony_ci		}
44798c2ecf20Sopenharmony_ci
44808c2ecf20Sopenharmony_ci		if (hci_conn_num(hdev, type) == num)
44818c2ecf20Sopenharmony_ci			break;
44828c2ecf20Sopenharmony_ci	}
44838c2ecf20Sopenharmony_ci
44848c2ecf20Sopenharmony_ci	rcu_read_unlock();
44858c2ecf20Sopenharmony_ci
44868c2ecf20Sopenharmony_ci}
44878c2ecf20Sopenharmony_ci
44888c2ecf20Sopenharmony_cistatic inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb)
44898c2ecf20Sopenharmony_ci{
44908c2ecf20Sopenharmony_ci	/* Calculate count of blocks used by this packet */
44918c2ecf20Sopenharmony_ci	return DIV_ROUND_UP(skb->len - HCI_ACL_HDR_SIZE, hdev->block_len);
44928c2ecf20Sopenharmony_ci}
44938c2ecf20Sopenharmony_ci
44948c2ecf20Sopenharmony_cistatic void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type)
44958c2ecf20Sopenharmony_ci{
44968c2ecf20Sopenharmony_ci	unsigned long last_tx;
44978c2ecf20Sopenharmony_ci
44988c2ecf20Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
44998c2ecf20Sopenharmony_ci		return;
45008c2ecf20Sopenharmony_ci
45018c2ecf20Sopenharmony_ci	switch (type) {
45028c2ecf20Sopenharmony_ci	case LE_LINK:
45038c2ecf20Sopenharmony_ci		last_tx = hdev->le_last_tx;
45048c2ecf20Sopenharmony_ci		break;
45058c2ecf20Sopenharmony_ci	default:
45068c2ecf20Sopenharmony_ci		last_tx = hdev->acl_last_tx;
45078c2ecf20Sopenharmony_ci		break;
45088c2ecf20Sopenharmony_ci	}
45098c2ecf20Sopenharmony_ci
45108c2ecf20Sopenharmony_ci	/* tx timeout must be longer than maximum link supervision timeout
45118c2ecf20Sopenharmony_ci	 * (40.9 seconds)
45128c2ecf20Sopenharmony_ci	 */
45138c2ecf20Sopenharmony_ci	if (!cnt && time_after(jiffies, last_tx + HCI_ACL_TX_TIMEOUT))
45148c2ecf20Sopenharmony_ci		hci_link_tx_to(hdev, type);
45158c2ecf20Sopenharmony_ci}
45168c2ecf20Sopenharmony_ci
45178c2ecf20Sopenharmony_ci/* Schedule SCO */
45188c2ecf20Sopenharmony_cistatic void hci_sched_sco(struct hci_dev *hdev)
45198c2ecf20Sopenharmony_ci{
45208c2ecf20Sopenharmony_ci	struct hci_conn *conn;
45218c2ecf20Sopenharmony_ci	struct sk_buff *skb;
45228c2ecf20Sopenharmony_ci	int quote;
45238c2ecf20Sopenharmony_ci
45248c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
45258c2ecf20Sopenharmony_ci
45268c2ecf20Sopenharmony_ci	if (!hci_conn_num(hdev, SCO_LINK))
45278c2ecf20Sopenharmony_ci		return;
45288c2ecf20Sopenharmony_ci
45298c2ecf20Sopenharmony_ci	while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, &quote))) {
45308c2ecf20Sopenharmony_ci		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
45318c2ecf20Sopenharmony_ci			BT_DBG("skb %p len %d", skb, skb->len);
45328c2ecf20Sopenharmony_ci			hci_send_frame(hdev, skb);
45338c2ecf20Sopenharmony_ci
45348c2ecf20Sopenharmony_ci			conn->sent++;
45358c2ecf20Sopenharmony_ci			if (conn->sent == ~0)
45368c2ecf20Sopenharmony_ci				conn->sent = 0;
45378c2ecf20Sopenharmony_ci		}
45388c2ecf20Sopenharmony_ci	}
45398c2ecf20Sopenharmony_ci}
45408c2ecf20Sopenharmony_ci
45418c2ecf20Sopenharmony_cistatic void hci_sched_esco(struct hci_dev *hdev)
45428c2ecf20Sopenharmony_ci{
45438c2ecf20Sopenharmony_ci	struct hci_conn *conn;
45448c2ecf20Sopenharmony_ci	struct sk_buff *skb;
45458c2ecf20Sopenharmony_ci	int quote;
45468c2ecf20Sopenharmony_ci
45478c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
45488c2ecf20Sopenharmony_ci
45498c2ecf20Sopenharmony_ci	if (!hci_conn_num(hdev, ESCO_LINK))
45508c2ecf20Sopenharmony_ci		return;
45518c2ecf20Sopenharmony_ci
45528c2ecf20Sopenharmony_ci	while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK,
45538c2ecf20Sopenharmony_ci						     &quote))) {
45548c2ecf20Sopenharmony_ci		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
45558c2ecf20Sopenharmony_ci			BT_DBG("skb %p len %d", skb, skb->len);
45568c2ecf20Sopenharmony_ci			hci_send_frame(hdev, skb);
45578c2ecf20Sopenharmony_ci
45588c2ecf20Sopenharmony_ci			conn->sent++;
45598c2ecf20Sopenharmony_ci			if (conn->sent == ~0)
45608c2ecf20Sopenharmony_ci				conn->sent = 0;
45618c2ecf20Sopenharmony_ci		}
45628c2ecf20Sopenharmony_ci	}
45638c2ecf20Sopenharmony_ci}
45648c2ecf20Sopenharmony_ci
45658c2ecf20Sopenharmony_cistatic void hci_sched_acl_pkt(struct hci_dev *hdev)
45668c2ecf20Sopenharmony_ci{
45678c2ecf20Sopenharmony_ci	unsigned int cnt = hdev->acl_cnt;
45688c2ecf20Sopenharmony_ci	struct hci_chan *chan;
45698c2ecf20Sopenharmony_ci	struct sk_buff *skb;
45708c2ecf20Sopenharmony_ci	int quote;
45718c2ecf20Sopenharmony_ci
45728c2ecf20Sopenharmony_ci	__check_timeout(hdev, cnt, ACL_LINK);
45738c2ecf20Sopenharmony_ci
45748c2ecf20Sopenharmony_ci	while (hdev->acl_cnt &&
45758c2ecf20Sopenharmony_ci	       (chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
45768c2ecf20Sopenharmony_ci		u32 priority = (skb_peek(&chan->data_q))->priority;
45778c2ecf20Sopenharmony_ci		while (quote-- && (skb = skb_peek(&chan->data_q))) {
45788c2ecf20Sopenharmony_ci			BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
45798c2ecf20Sopenharmony_ci			       skb->len, skb->priority);
45808c2ecf20Sopenharmony_ci
45818c2ecf20Sopenharmony_ci			/* Stop if priority has changed */
45828c2ecf20Sopenharmony_ci			if (skb->priority < priority)
45838c2ecf20Sopenharmony_ci				break;
45848c2ecf20Sopenharmony_ci
45858c2ecf20Sopenharmony_ci			skb = skb_dequeue(&chan->data_q);
45868c2ecf20Sopenharmony_ci
45878c2ecf20Sopenharmony_ci			hci_conn_enter_active_mode(chan->conn,
45888c2ecf20Sopenharmony_ci						   bt_cb(skb)->force_active);
45898c2ecf20Sopenharmony_ci
45908c2ecf20Sopenharmony_ci			hci_send_frame(hdev, skb);
45918c2ecf20Sopenharmony_ci			hdev->acl_last_tx = jiffies;
45928c2ecf20Sopenharmony_ci
45938c2ecf20Sopenharmony_ci			hdev->acl_cnt--;
45948c2ecf20Sopenharmony_ci			chan->sent++;
45958c2ecf20Sopenharmony_ci			chan->conn->sent++;
45968c2ecf20Sopenharmony_ci
45978c2ecf20Sopenharmony_ci			/* Send pending SCO packets right away */
45988c2ecf20Sopenharmony_ci			hci_sched_sco(hdev);
45998c2ecf20Sopenharmony_ci			hci_sched_esco(hdev);
46008c2ecf20Sopenharmony_ci		}
46018c2ecf20Sopenharmony_ci	}
46028c2ecf20Sopenharmony_ci
46038c2ecf20Sopenharmony_ci	if (cnt != hdev->acl_cnt)
46048c2ecf20Sopenharmony_ci		hci_prio_recalculate(hdev, ACL_LINK);
46058c2ecf20Sopenharmony_ci}
46068c2ecf20Sopenharmony_ci
46078c2ecf20Sopenharmony_cistatic void hci_sched_acl_blk(struct hci_dev *hdev)
46088c2ecf20Sopenharmony_ci{
46098c2ecf20Sopenharmony_ci	unsigned int cnt = hdev->block_cnt;
46108c2ecf20Sopenharmony_ci	struct hci_chan *chan;
46118c2ecf20Sopenharmony_ci	struct sk_buff *skb;
46128c2ecf20Sopenharmony_ci	int quote;
46138c2ecf20Sopenharmony_ci	u8 type;
46148c2ecf20Sopenharmony_ci
46158c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
46168c2ecf20Sopenharmony_ci
46178c2ecf20Sopenharmony_ci	if (hdev->dev_type == HCI_AMP)
46188c2ecf20Sopenharmony_ci		type = AMP_LINK;
46198c2ecf20Sopenharmony_ci	else
46208c2ecf20Sopenharmony_ci		type = ACL_LINK;
46218c2ecf20Sopenharmony_ci
46228c2ecf20Sopenharmony_ci	__check_timeout(hdev, cnt, type);
46238c2ecf20Sopenharmony_ci
46248c2ecf20Sopenharmony_ci	while (hdev->block_cnt > 0 &&
46258c2ecf20Sopenharmony_ci	       (chan = hci_chan_sent(hdev, type, &quote))) {
46268c2ecf20Sopenharmony_ci		u32 priority = (skb_peek(&chan->data_q))->priority;
46278c2ecf20Sopenharmony_ci		while (quote > 0 && (skb = skb_peek(&chan->data_q))) {
46288c2ecf20Sopenharmony_ci			int blocks;
46298c2ecf20Sopenharmony_ci
46308c2ecf20Sopenharmony_ci			BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
46318c2ecf20Sopenharmony_ci			       skb->len, skb->priority);
46328c2ecf20Sopenharmony_ci
46338c2ecf20Sopenharmony_ci			/* Stop if priority has changed */
46348c2ecf20Sopenharmony_ci			if (skb->priority < priority)
46358c2ecf20Sopenharmony_ci				break;
46368c2ecf20Sopenharmony_ci
46378c2ecf20Sopenharmony_ci			skb = skb_dequeue(&chan->data_q);
46388c2ecf20Sopenharmony_ci
46398c2ecf20Sopenharmony_ci			blocks = __get_blocks(hdev, skb);
46408c2ecf20Sopenharmony_ci			if (blocks > hdev->block_cnt)
46418c2ecf20Sopenharmony_ci				return;
46428c2ecf20Sopenharmony_ci
46438c2ecf20Sopenharmony_ci			hci_conn_enter_active_mode(chan->conn,
46448c2ecf20Sopenharmony_ci						   bt_cb(skb)->force_active);
46458c2ecf20Sopenharmony_ci
46468c2ecf20Sopenharmony_ci			hci_send_frame(hdev, skb);
46478c2ecf20Sopenharmony_ci			hdev->acl_last_tx = jiffies;
46488c2ecf20Sopenharmony_ci
46498c2ecf20Sopenharmony_ci			hdev->block_cnt -= blocks;
46508c2ecf20Sopenharmony_ci			quote -= blocks;
46518c2ecf20Sopenharmony_ci
46528c2ecf20Sopenharmony_ci			chan->sent += blocks;
46538c2ecf20Sopenharmony_ci			chan->conn->sent += blocks;
46548c2ecf20Sopenharmony_ci		}
46558c2ecf20Sopenharmony_ci	}
46568c2ecf20Sopenharmony_ci
46578c2ecf20Sopenharmony_ci	if (cnt != hdev->block_cnt)
46588c2ecf20Sopenharmony_ci		hci_prio_recalculate(hdev, type);
46598c2ecf20Sopenharmony_ci}
46608c2ecf20Sopenharmony_ci
46618c2ecf20Sopenharmony_cistatic void hci_sched_acl(struct hci_dev *hdev)
46628c2ecf20Sopenharmony_ci{
46638c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
46648c2ecf20Sopenharmony_ci
46658c2ecf20Sopenharmony_ci	/* No ACL link over BR/EDR controller */
46668c2ecf20Sopenharmony_ci	if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_PRIMARY)
46678c2ecf20Sopenharmony_ci		return;
46688c2ecf20Sopenharmony_ci
46698c2ecf20Sopenharmony_ci	/* No AMP link over AMP controller */
46708c2ecf20Sopenharmony_ci	if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP)
46718c2ecf20Sopenharmony_ci		return;
46728c2ecf20Sopenharmony_ci
46738c2ecf20Sopenharmony_ci	switch (hdev->flow_ctl_mode) {
46748c2ecf20Sopenharmony_ci	case HCI_FLOW_CTL_MODE_PACKET_BASED:
46758c2ecf20Sopenharmony_ci		hci_sched_acl_pkt(hdev);
46768c2ecf20Sopenharmony_ci		break;
46778c2ecf20Sopenharmony_ci
46788c2ecf20Sopenharmony_ci	case HCI_FLOW_CTL_MODE_BLOCK_BASED:
46798c2ecf20Sopenharmony_ci		hci_sched_acl_blk(hdev);
46808c2ecf20Sopenharmony_ci		break;
46818c2ecf20Sopenharmony_ci	}
46828c2ecf20Sopenharmony_ci}
46838c2ecf20Sopenharmony_ci
46848c2ecf20Sopenharmony_cistatic void hci_sched_le(struct hci_dev *hdev)
46858c2ecf20Sopenharmony_ci{
46868c2ecf20Sopenharmony_ci	struct hci_chan *chan;
46878c2ecf20Sopenharmony_ci	struct sk_buff *skb;
46888c2ecf20Sopenharmony_ci	int quote, cnt, tmp;
46898c2ecf20Sopenharmony_ci
46908c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
46918c2ecf20Sopenharmony_ci
46928c2ecf20Sopenharmony_ci	if (!hci_conn_num(hdev, LE_LINK))
46938c2ecf20Sopenharmony_ci		return;
46948c2ecf20Sopenharmony_ci
46958c2ecf20Sopenharmony_ci	cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
46968c2ecf20Sopenharmony_ci
46978c2ecf20Sopenharmony_ci	__check_timeout(hdev, cnt, LE_LINK);
46988c2ecf20Sopenharmony_ci
46998c2ecf20Sopenharmony_ci	tmp = cnt;
47008c2ecf20Sopenharmony_ci	while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, &quote))) {
47018c2ecf20Sopenharmony_ci		u32 priority = (skb_peek(&chan->data_q))->priority;
47028c2ecf20Sopenharmony_ci		while (quote-- && (skb = skb_peek(&chan->data_q))) {
47038c2ecf20Sopenharmony_ci			BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
47048c2ecf20Sopenharmony_ci			       skb->len, skb->priority);
47058c2ecf20Sopenharmony_ci
47068c2ecf20Sopenharmony_ci			/* Stop if priority has changed */
47078c2ecf20Sopenharmony_ci			if (skb->priority < priority)
47088c2ecf20Sopenharmony_ci				break;
47098c2ecf20Sopenharmony_ci
47108c2ecf20Sopenharmony_ci			skb = skb_dequeue(&chan->data_q);
47118c2ecf20Sopenharmony_ci
47128c2ecf20Sopenharmony_ci			hci_send_frame(hdev, skb);
47138c2ecf20Sopenharmony_ci			hdev->le_last_tx = jiffies;
47148c2ecf20Sopenharmony_ci
47158c2ecf20Sopenharmony_ci			cnt--;
47168c2ecf20Sopenharmony_ci			chan->sent++;
47178c2ecf20Sopenharmony_ci			chan->conn->sent++;
47188c2ecf20Sopenharmony_ci
47198c2ecf20Sopenharmony_ci			/* Send pending SCO packets right away */
47208c2ecf20Sopenharmony_ci			hci_sched_sco(hdev);
47218c2ecf20Sopenharmony_ci			hci_sched_esco(hdev);
47228c2ecf20Sopenharmony_ci		}
47238c2ecf20Sopenharmony_ci	}
47248c2ecf20Sopenharmony_ci
47258c2ecf20Sopenharmony_ci	if (hdev->le_pkts)
47268c2ecf20Sopenharmony_ci		hdev->le_cnt = cnt;
47278c2ecf20Sopenharmony_ci	else
47288c2ecf20Sopenharmony_ci		hdev->acl_cnt = cnt;
47298c2ecf20Sopenharmony_ci
47308c2ecf20Sopenharmony_ci	if (cnt != tmp)
47318c2ecf20Sopenharmony_ci		hci_prio_recalculate(hdev, LE_LINK);
47328c2ecf20Sopenharmony_ci}
47338c2ecf20Sopenharmony_ci
47348c2ecf20Sopenharmony_cistatic void hci_tx_work(struct work_struct *work)
47358c2ecf20Sopenharmony_ci{
47368c2ecf20Sopenharmony_ci	struct hci_dev *hdev = container_of(work, struct hci_dev, tx_work);
47378c2ecf20Sopenharmony_ci	struct sk_buff *skb;
47388c2ecf20Sopenharmony_ci
47398c2ecf20Sopenharmony_ci	BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
47408c2ecf20Sopenharmony_ci	       hdev->sco_cnt, hdev->le_cnt);
47418c2ecf20Sopenharmony_ci
47428c2ecf20Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
47438c2ecf20Sopenharmony_ci		/* Schedule queues and send stuff to HCI driver */
47448c2ecf20Sopenharmony_ci		hci_sched_sco(hdev);
47458c2ecf20Sopenharmony_ci		hci_sched_esco(hdev);
47468c2ecf20Sopenharmony_ci		hci_sched_acl(hdev);
47478c2ecf20Sopenharmony_ci		hci_sched_le(hdev);
47488c2ecf20Sopenharmony_ci	}
47498c2ecf20Sopenharmony_ci
47508c2ecf20Sopenharmony_ci	/* Send next queued raw (unknown type) packet */
47518c2ecf20Sopenharmony_ci	while ((skb = skb_dequeue(&hdev->raw_q)))
47528c2ecf20Sopenharmony_ci		hci_send_frame(hdev, skb);
47538c2ecf20Sopenharmony_ci}
47548c2ecf20Sopenharmony_ci
47558c2ecf20Sopenharmony_ci/* ----- HCI RX task (incoming data processing) ----- */
47568c2ecf20Sopenharmony_ci
47578c2ecf20Sopenharmony_ci/* ACL data packet */
47588c2ecf20Sopenharmony_cistatic void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
47598c2ecf20Sopenharmony_ci{
47608c2ecf20Sopenharmony_ci	struct hci_acl_hdr *hdr = (void *) skb->data;
47618c2ecf20Sopenharmony_ci	struct hci_conn *conn;
47628c2ecf20Sopenharmony_ci	__u16 handle, flags;
47638c2ecf20Sopenharmony_ci
47648c2ecf20Sopenharmony_ci	skb_pull(skb, HCI_ACL_HDR_SIZE);
47658c2ecf20Sopenharmony_ci
47668c2ecf20Sopenharmony_ci	handle = __le16_to_cpu(hdr->handle);
47678c2ecf20Sopenharmony_ci	flags  = hci_flags(handle);
47688c2ecf20Sopenharmony_ci	handle = hci_handle(handle);
47698c2ecf20Sopenharmony_ci
47708c2ecf20Sopenharmony_ci	BT_DBG("%s len %d handle 0x%4.4x flags 0x%4.4x", hdev->name, skb->len,
47718c2ecf20Sopenharmony_ci	       handle, flags);
47728c2ecf20Sopenharmony_ci
47738c2ecf20Sopenharmony_ci	hdev->stat.acl_rx++;
47748c2ecf20Sopenharmony_ci
47758c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
47768c2ecf20Sopenharmony_ci	conn = hci_conn_hash_lookup_handle(hdev, handle);
47778c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
47788c2ecf20Sopenharmony_ci
47798c2ecf20Sopenharmony_ci	if (conn) {
47808c2ecf20Sopenharmony_ci		hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
47818c2ecf20Sopenharmony_ci
47828c2ecf20Sopenharmony_ci		/* Send to upper protocol */
47838c2ecf20Sopenharmony_ci		l2cap_recv_acldata(conn, skb, flags);
47848c2ecf20Sopenharmony_ci		return;
47858c2ecf20Sopenharmony_ci	} else {
47868c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "ACL packet for unknown connection handle %d",
47878c2ecf20Sopenharmony_ci			   handle);
47888c2ecf20Sopenharmony_ci	}
47898c2ecf20Sopenharmony_ci
47908c2ecf20Sopenharmony_ci	kfree_skb(skb);
47918c2ecf20Sopenharmony_ci}
47928c2ecf20Sopenharmony_ci
47938c2ecf20Sopenharmony_ci/* SCO data packet */
47948c2ecf20Sopenharmony_cistatic void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
47958c2ecf20Sopenharmony_ci{
47968c2ecf20Sopenharmony_ci	struct hci_sco_hdr *hdr = (void *) skb->data;
47978c2ecf20Sopenharmony_ci	struct hci_conn *conn;
47988c2ecf20Sopenharmony_ci	__u16 handle, flags;
47998c2ecf20Sopenharmony_ci
48008c2ecf20Sopenharmony_ci	skb_pull(skb, HCI_SCO_HDR_SIZE);
48018c2ecf20Sopenharmony_ci
48028c2ecf20Sopenharmony_ci	handle = __le16_to_cpu(hdr->handle);
48038c2ecf20Sopenharmony_ci	flags  = hci_flags(handle);
48048c2ecf20Sopenharmony_ci	handle = hci_handle(handle);
48058c2ecf20Sopenharmony_ci
48068c2ecf20Sopenharmony_ci	BT_DBG("%s len %d handle 0x%4.4x flags 0x%4.4x", hdev->name, skb->len,
48078c2ecf20Sopenharmony_ci	       handle, flags);
48088c2ecf20Sopenharmony_ci
48098c2ecf20Sopenharmony_ci	hdev->stat.sco_rx++;
48108c2ecf20Sopenharmony_ci
48118c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
48128c2ecf20Sopenharmony_ci	conn = hci_conn_hash_lookup_handle(hdev, handle);
48138c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
48148c2ecf20Sopenharmony_ci
48158c2ecf20Sopenharmony_ci	if (conn) {
48168c2ecf20Sopenharmony_ci		/* Send to upper protocol */
48178c2ecf20Sopenharmony_ci		bt_cb(skb)->sco.pkt_status = flags & 0x03;
48188c2ecf20Sopenharmony_ci		sco_recv_scodata(conn, skb);
48198c2ecf20Sopenharmony_ci		return;
48208c2ecf20Sopenharmony_ci	} else {
48218c2ecf20Sopenharmony_ci		bt_dev_err(hdev, "SCO packet for unknown connection handle %d",
48228c2ecf20Sopenharmony_ci			   handle);
48238c2ecf20Sopenharmony_ci	}
48248c2ecf20Sopenharmony_ci
48258c2ecf20Sopenharmony_ci	kfree_skb(skb);
48268c2ecf20Sopenharmony_ci}
48278c2ecf20Sopenharmony_ci
48288c2ecf20Sopenharmony_cistatic bool hci_req_is_complete(struct hci_dev *hdev)
48298c2ecf20Sopenharmony_ci{
48308c2ecf20Sopenharmony_ci	struct sk_buff *skb;
48318c2ecf20Sopenharmony_ci
48328c2ecf20Sopenharmony_ci	skb = skb_peek(&hdev->cmd_q);
48338c2ecf20Sopenharmony_ci	if (!skb)
48348c2ecf20Sopenharmony_ci		return true;
48358c2ecf20Sopenharmony_ci
48368c2ecf20Sopenharmony_ci	return (bt_cb(skb)->hci.req_flags & HCI_REQ_START);
48378c2ecf20Sopenharmony_ci}
48388c2ecf20Sopenharmony_ci
48398c2ecf20Sopenharmony_cistatic void hci_resend_last(struct hci_dev *hdev)
48408c2ecf20Sopenharmony_ci{
48418c2ecf20Sopenharmony_ci	struct hci_command_hdr *sent;
48428c2ecf20Sopenharmony_ci	struct sk_buff *skb;
48438c2ecf20Sopenharmony_ci	u16 opcode;
48448c2ecf20Sopenharmony_ci
48458c2ecf20Sopenharmony_ci	if (!hdev->sent_cmd)
48468c2ecf20Sopenharmony_ci		return;
48478c2ecf20Sopenharmony_ci
48488c2ecf20Sopenharmony_ci	sent = (void *) hdev->sent_cmd->data;
48498c2ecf20Sopenharmony_ci	opcode = __le16_to_cpu(sent->opcode);
48508c2ecf20Sopenharmony_ci	if (opcode == HCI_OP_RESET)
48518c2ecf20Sopenharmony_ci		return;
48528c2ecf20Sopenharmony_ci
48538c2ecf20Sopenharmony_ci	skb = skb_clone(hdev->sent_cmd, GFP_KERNEL);
48548c2ecf20Sopenharmony_ci	if (!skb)
48558c2ecf20Sopenharmony_ci		return;
48568c2ecf20Sopenharmony_ci
48578c2ecf20Sopenharmony_ci	skb_queue_head(&hdev->cmd_q, skb);
48588c2ecf20Sopenharmony_ci	queue_work(hdev->workqueue, &hdev->cmd_work);
48598c2ecf20Sopenharmony_ci}
48608c2ecf20Sopenharmony_ci
48618c2ecf20Sopenharmony_civoid hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
48628c2ecf20Sopenharmony_ci			  hci_req_complete_t *req_complete,
48638c2ecf20Sopenharmony_ci			  hci_req_complete_skb_t *req_complete_skb)
48648c2ecf20Sopenharmony_ci{
48658c2ecf20Sopenharmony_ci	struct sk_buff *skb;
48668c2ecf20Sopenharmony_ci	unsigned long flags;
48678c2ecf20Sopenharmony_ci
48688c2ecf20Sopenharmony_ci	BT_DBG("opcode 0x%04x status 0x%02x", opcode, status);
48698c2ecf20Sopenharmony_ci
48708c2ecf20Sopenharmony_ci	/* If the completed command doesn't match the last one that was
48718c2ecf20Sopenharmony_ci	 * sent we need to do special handling of it.
48728c2ecf20Sopenharmony_ci	 */
48738c2ecf20Sopenharmony_ci	if (!hci_sent_cmd_data(hdev, opcode)) {
48748c2ecf20Sopenharmony_ci		/* Some CSR based controllers generate a spontaneous
48758c2ecf20Sopenharmony_ci		 * reset complete event during init and any pending
48768c2ecf20Sopenharmony_ci		 * command will never be completed. In such a case we
48778c2ecf20Sopenharmony_ci		 * need to resend whatever was the last sent
48788c2ecf20Sopenharmony_ci		 * command.
48798c2ecf20Sopenharmony_ci		 */
48808c2ecf20Sopenharmony_ci		if (test_bit(HCI_INIT, &hdev->flags) && opcode == HCI_OP_RESET)
48818c2ecf20Sopenharmony_ci			hci_resend_last(hdev);
48828c2ecf20Sopenharmony_ci
48838c2ecf20Sopenharmony_ci		return;
48848c2ecf20Sopenharmony_ci	}
48858c2ecf20Sopenharmony_ci
48868c2ecf20Sopenharmony_ci	/* If we reach this point this event matches the last command sent */
48878c2ecf20Sopenharmony_ci	hci_dev_clear_flag(hdev, HCI_CMD_PENDING);
48888c2ecf20Sopenharmony_ci
48898c2ecf20Sopenharmony_ci	/* If the command succeeded and there's still more commands in
48908c2ecf20Sopenharmony_ci	 * this request the request is not yet complete.
48918c2ecf20Sopenharmony_ci	 */
48928c2ecf20Sopenharmony_ci	if (!status && !hci_req_is_complete(hdev))
48938c2ecf20Sopenharmony_ci		return;
48948c2ecf20Sopenharmony_ci
48958c2ecf20Sopenharmony_ci	/* If this was the last command in a request the complete
48968c2ecf20Sopenharmony_ci	 * callback would be found in hdev->sent_cmd instead of the
48978c2ecf20Sopenharmony_ci	 * command queue (hdev->cmd_q).
48988c2ecf20Sopenharmony_ci	 */
48998c2ecf20Sopenharmony_ci	if (bt_cb(hdev->sent_cmd)->hci.req_flags & HCI_REQ_SKB) {
49008c2ecf20Sopenharmony_ci		*req_complete_skb = bt_cb(hdev->sent_cmd)->hci.req_complete_skb;
49018c2ecf20Sopenharmony_ci		return;
49028c2ecf20Sopenharmony_ci	}
49038c2ecf20Sopenharmony_ci
49048c2ecf20Sopenharmony_ci	if (bt_cb(hdev->sent_cmd)->hci.req_complete) {
49058c2ecf20Sopenharmony_ci		*req_complete = bt_cb(hdev->sent_cmd)->hci.req_complete;
49068c2ecf20Sopenharmony_ci		return;
49078c2ecf20Sopenharmony_ci	}
49088c2ecf20Sopenharmony_ci
49098c2ecf20Sopenharmony_ci	/* Remove all pending commands belonging to this request */
49108c2ecf20Sopenharmony_ci	spin_lock_irqsave(&hdev->cmd_q.lock, flags);
49118c2ecf20Sopenharmony_ci	while ((skb = __skb_dequeue(&hdev->cmd_q))) {
49128c2ecf20Sopenharmony_ci		if (bt_cb(skb)->hci.req_flags & HCI_REQ_START) {
49138c2ecf20Sopenharmony_ci			__skb_queue_head(&hdev->cmd_q, skb);
49148c2ecf20Sopenharmony_ci			break;
49158c2ecf20Sopenharmony_ci		}
49168c2ecf20Sopenharmony_ci
49178c2ecf20Sopenharmony_ci		if (bt_cb(skb)->hci.req_flags & HCI_REQ_SKB)
49188c2ecf20Sopenharmony_ci			*req_complete_skb = bt_cb(skb)->hci.req_complete_skb;
49198c2ecf20Sopenharmony_ci		else
49208c2ecf20Sopenharmony_ci			*req_complete = bt_cb(skb)->hci.req_complete;
49218c2ecf20Sopenharmony_ci		dev_kfree_skb_irq(skb);
49228c2ecf20Sopenharmony_ci	}
49238c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&hdev->cmd_q.lock, flags);
49248c2ecf20Sopenharmony_ci}
49258c2ecf20Sopenharmony_ci
49268c2ecf20Sopenharmony_cistatic void hci_rx_work(struct work_struct *work)
49278c2ecf20Sopenharmony_ci{
49288c2ecf20Sopenharmony_ci	struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work);
49298c2ecf20Sopenharmony_ci	struct sk_buff *skb;
49308c2ecf20Sopenharmony_ci
49318c2ecf20Sopenharmony_ci	BT_DBG("%s", hdev->name);
49328c2ecf20Sopenharmony_ci
49338c2ecf20Sopenharmony_ci	while ((skb = skb_dequeue(&hdev->rx_q))) {
49348c2ecf20Sopenharmony_ci		/* Send copy to monitor */
49358c2ecf20Sopenharmony_ci		hci_send_to_monitor(hdev, skb);
49368c2ecf20Sopenharmony_ci
49378c2ecf20Sopenharmony_ci		if (atomic_read(&hdev->promisc)) {
49388c2ecf20Sopenharmony_ci			/* Send copy to the sockets */
49398c2ecf20Sopenharmony_ci			hci_send_to_sock(hdev, skb);
49408c2ecf20Sopenharmony_ci		}
49418c2ecf20Sopenharmony_ci
49428c2ecf20Sopenharmony_ci		/* If the device has been opened in HCI_USER_CHANNEL,
49438c2ecf20Sopenharmony_ci		 * the userspace has exclusive access to device.
49448c2ecf20Sopenharmony_ci		 * When device is HCI_INIT, we still need to process
49458c2ecf20Sopenharmony_ci		 * the data packets to the driver in order
49468c2ecf20Sopenharmony_ci		 * to complete its setup().
49478c2ecf20Sopenharmony_ci		 */
49488c2ecf20Sopenharmony_ci		if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
49498c2ecf20Sopenharmony_ci		    !test_bit(HCI_INIT, &hdev->flags)) {
49508c2ecf20Sopenharmony_ci			kfree_skb(skb);
49518c2ecf20Sopenharmony_ci			continue;
49528c2ecf20Sopenharmony_ci		}
49538c2ecf20Sopenharmony_ci
49548c2ecf20Sopenharmony_ci		if (test_bit(HCI_INIT, &hdev->flags)) {
49558c2ecf20Sopenharmony_ci			/* Don't process data packets in this states. */
49568c2ecf20Sopenharmony_ci			switch (hci_skb_pkt_type(skb)) {
49578c2ecf20Sopenharmony_ci			case HCI_ACLDATA_PKT:
49588c2ecf20Sopenharmony_ci			case HCI_SCODATA_PKT:
49598c2ecf20Sopenharmony_ci			case HCI_ISODATA_PKT:
49608c2ecf20Sopenharmony_ci				kfree_skb(skb);
49618c2ecf20Sopenharmony_ci				continue;
49628c2ecf20Sopenharmony_ci			}
49638c2ecf20Sopenharmony_ci		}
49648c2ecf20Sopenharmony_ci
49658c2ecf20Sopenharmony_ci		/* Process frame */
49668c2ecf20Sopenharmony_ci		switch (hci_skb_pkt_type(skb)) {
49678c2ecf20Sopenharmony_ci		case HCI_EVENT_PKT:
49688c2ecf20Sopenharmony_ci			BT_DBG("%s Event packet", hdev->name);
49698c2ecf20Sopenharmony_ci			hci_event_packet(hdev, skb);
49708c2ecf20Sopenharmony_ci			break;
49718c2ecf20Sopenharmony_ci
49728c2ecf20Sopenharmony_ci		case HCI_ACLDATA_PKT:
49738c2ecf20Sopenharmony_ci			BT_DBG("%s ACL data packet", hdev->name);
49748c2ecf20Sopenharmony_ci			hci_acldata_packet(hdev, skb);
49758c2ecf20Sopenharmony_ci			break;
49768c2ecf20Sopenharmony_ci
49778c2ecf20Sopenharmony_ci		case HCI_SCODATA_PKT:
49788c2ecf20Sopenharmony_ci			BT_DBG("%s SCO data packet", hdev->name);
49798c2ecf20Sopenharmony_ci			hci_scodata_packet(hdev, skb);
49808c2ecf20Sopenharmony_ci			break;
49818c2ecf20Sopenharmony_ci
49828c2ecf20Sopenharmony_ci		default:
49838c2ecf20Sopenharmony_ci			kfree_skb(skb);
49848c2ecf20Sopenharmony_ci			break;
49858c2ecf20Sopenharmony_ci		}
49868c2ecf20Sopenharmony_ci	}
49878c2ecf20Sopenharmony_ci}
49888c2ecf20Sopenharmony_ci
49898c2ecf20Sopenharmony_cistatic void hci_cmd_work(struct work_struct *work)
49908c2ecf20Sopenharmony_ci{
49918c2ecf20Sopenharmony_ci	struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work);
49928c2ecf20Sopenharmony_ci	struct sk_buff *skb;
49938c2ecf20Sopenharmony_ci
49948c2ecf20Sopenharmony_ci	BT_DBG("%s cmd_cnt %d cmd queued %d", hdev->name,
49958c2ecf20Sopenharmony_ci	       atomic_read(&hdev->cmd_cnt), skb_queue_len(&hdev->cmd_q));
49968c2ecf20Sopenharmony_ci
49978c2ecf20Sopenharmony_ci	/* Send queued commands */
49988c2ecf20Sopenharmony_ci	if (atomic_read(&hdev->cmd_cnt)) {
49998c2ecf20Sopenharmony_ci		skb = skb_dequeue(&hdev->cmd_q);
50008c2ecf20Sopenharmony_ci		if (!skb)
50018c2ecf20Sopenharmony_ci			return;
50028c2ecf20Sopenharmony_ci
50038c2ecf20Sopenharmony_ci		kfree_skb(hdev->sent_cmd);
50048c2ecf20Sopenharmony_ci
50058c2ecf20Sopenharmony_ci		hdev->sent_cmd = skb_clone(skb, GFP_KERNEL);
50068c2ecf20Sopenharmony_ci		if (hdev->sent_cmd) {
50078c2ecf20Sopenharmony_ci			if (hci_req_status_pend(hdev))
50088c2ecf20Sopenharmony_ci				hci_dev_set_flag(hdev, HCI_CMD_PENDING);
50098c2ecf20Sopenharmony_ci			atomic_dec(&hdev->cmd_cnt);
50108c2ecf20Sopenharmony_ci			hci_send_frame(hdev, skb);
50118c2ecf20Sopenharmony_ci			if (test_bit(HCI_RESET, &hdev->flags))
50128c2ecf20Sopenharmony_ci				cancel_delayed_work(&hdev->cmd_timer);
50138c2ecf20Sopenharmony_ci			else
50148c2ecf20Sopenharmony_ci				schedule_delayed_work(&hdev->cmd_timer,
50158c2ecf20Sopenharmony_ci						      HCI_CMD_TIMEOUT);
50168c2ecf20Sopenharmony_ci		} else {
50178c2ecf20Sopenharmony_ci			skb_queue_head(&hdev->cmd_q, skb);
50188c2ecf20Sopenharmony_ci			queue_work(hdev->workqueue, &hdev->cmd_work);
50198c2ecf20Sopenharmony_ci		}
50208c2ecf20Sopenharmony_ci	}
50218c2ecf20Sopenharmony_ci}
5022