summaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2015-10-17 16:00:26 +0200
committerMarcel Holtmann <marcel@holtmann.org>2015-10-21 00:49:22 +0200
commit7e995b9eadbe226e355b785a765fd90fe0487414 (patch)
treef92151bf1a1740fef69b29c9412bdb26d09bc655 /net/bluetooth
parent7841d06e4398cff7d744539d1e6ea4026ceab2e5 (diff)
downloadlinux-7e995b9eadbe226e355b785a765fd90fe0487414.tar.bz2
Bluetooth: Add new quirk for non-persistent diagnostic settings
If the diagnostic settings are not persistent over HCI Reset, then this quirk can be used to tell the Bluetoth core about it. This will ensure that the settings are programmed correctly when the controller is powered up. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_core.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b36a2e5693d2..f33268004195 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -162,6 +162,16 @@ static ssize_t vendor_diag_write(struct file *file, const char __user *user_buf,
if (strtobool(buf, &enable))
return -EINVAL;
+ /* When the diagnostic flags are not persistent and the transport
+ * is not active, then there is no need for the vendor callback.
+ *
+ * Instead just store the desired value. If needed the setting
+ * will be programmed when the controller gets powered on.
+ */
+ if (test_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks) &&
+ !test_bit(HCI_RUNNING, &hdev->flags))
+ goto done;
+
hci_req_lock(hdev);
err = hdev->set_diag(hdev, enable);
hci_req_unlock(hdev);
@@ -169,6 +179,7 @@ static ssize_t vendor_diag_write(struct file *file, const char __user *user_buf,
if (err < 0)
return err;
+done:
if (enable)
hci_dev_set_flag(hdev, HCI_VENDOR_DIAG);
else
@@ -1494,6 +1505,14 @@ static int hci_dev_do_open(struct hci_dev *hdev)
ret = __hci_init(hdev);
}
+ /* If the HCI Reset command is clearing all diagnostic settings,
+ * then they need to be reprogrammed after the init procedure
+ * completed.
+ */
+ if (test_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks) &&
+ hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) && hdev->set_diag)
+ ret = hdev->set_diag(hdev, true);
+
clear_bit(HCI_INIT, &hdev->flags);
if (!ret) {