summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-07-06 12:11:14 +0200
committerJohan Hedberg <johan.hedberg@intel.com>2014-07-06 13:41:51 +0300
commitd603b76b0c18c5adf4a3164dff50bb15948cd7bd (patch)
tree0bce0af1355d27fa8658d81875c3602cf3332475 /net/bluetooth/mgmt.c
parent19de0825cd8acb1de6fa6a135b1f059446781049 (diff)
downloadlinux-stable-d603b76b0c18c5adf4a3164dff50bb15948cd7bd.tar.gz
linux-stable-d603b76b0c18c5adf4a3164dff50bb15948cd7bd.tar.bz2
linux-stable-d603b76b0c18c5adf4a3164dff50bb15948cd7bd.zip
Bluetooth: Run controller setup after external configuration
When the external configuration triggers the switch to a configured controller, it means the setup needs to be run. Controllers that start out unconfigured have only run limited set of HCI commands. This is not enough for complete operation and thus run the setup procedure before announcing the new controller index. This introduces HCI_CONFIG flag as companion to HCI_SETUP flag. The HCI_SETUP flag is only used once for the initial setup procedure. And during that procedure hdev->setup driver callback is called. With the new HCI_CONFIG the switch from unconfigured to configured state is triggering the same setup procedure just without hdev->setup. This is required since bringing a controller back to unconfigured state from configured state is possible. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 04a66429ad4d..d66463a52280 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -385,6 +385,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
count = 0;
list_for_each_entry(d, &hci_dev_list, list) {
if (test_bit(HCI_SETUP, &d->dev_flags) ||
+ test_bit(HCI_CONFIG, &d->dev_flags) ||
test_bit(HCI_USER_CHANNEL, &d->dev_flags))
continue;
@@ -444,6 +445,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
count = 0;
list_for_each_entry(d, &hci_dev_list, list) {
if (test_bit(HCI_SETUP, &d->dev_flags) ||
+ test_bit(HCI_CONFIG, &d->dev_flags) ||
test_bit(HCI_USER_CHANNEL, &d->dev_flags))
continue;
@@ -5441,8 +5443,15 @@ static int set_external_config(struct sock *sk, struct hci_dev *hdev,
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
mgmt_index_removed(hdev);
- change_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
- mgmt_index_added(hdev);
+
+ if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
+ set_bit(HCI_CONFIG, &hdev->dev_flags);
+ set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
+
+ queue_work(hdev->req_workqueue, &hdev->power_on);
+ } else {
+ mgmt_index_added(hdev);
+ }
}
unlock:
@@ -5558,6 +5567,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
}
if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
+ test_bit(HCI_CONFIG, &hdev->dev_flags) ||
test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
err = cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_INDEX);