Bluetooth: Add new state HCI_POWERING_DOWN
authorJonas Dreßler <verdre@v0yd.nl>
Sun, 7 Jan 2024 18:02:49 +0000 (19:02 +0100)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 6 Mar 2024 22:22:37 +0000 (17:22 -0500)
Add a new state HCI_POWERING_DOWN that indicates that the device is
currently powering down, this will be useful for the next commit.

Signed-off-by: Jonas Dreßler <verdre@v0yd.nl>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
include/net/bluetooth/hci.h
net/bluetooth/hci_sync.c
net/bluetooth/mgmt.c

index f7918c7..a94a849 100644 (file)
@@ -372,6 +372,7 @@ enum {
        HCI_SETUP,
        HCI_CONFIG,
        HCI_DEBUGFS_CREATED,
+       HCI_POWERING_DOWN,
        HCI_AUTO_OFF,
        HCI_RFKILLED,
        HCI_MGMT,
index 5716345..b146562 100644 (file)
@@ -5403,27 +5403,33 @@ static int hci_power_off_sync(struct hci_dev *hdev)
        if (!test_bit(HCI_UP, &hdev->flags))
                return 0;
 
+       hci_dev_set_flag(hdev, HCI_POWERING_DOWN);
+
        if (test_bit(HCI_ISCAN, &hdev->flags) ||
            test_bit(HCI_PSCAN, &hdev->flags)) {
                err = hci_write_scan_enable_sync(hdev, 0x00);
                if (err)
-                       return err;
+                       goto out;
        }
 
        err = hci_clear_adv_sync(hdev, NULL, false);
        if (err)
-               return err;
+               goto out;
 
        err = hci_stop_discovery_sync(hdev);
        if (err)
-               return err;
+               goto out;
 
        /* Terminated due to Power Off */
        err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
        if (err)
-               return err;
+               goto out;
+
+       err = hci_dev_close_sync(hdev);
 
-       return hci_dev_close_sync(hdev);
+out:
+       hci_dev_clear_flag(hdev, HCI_POWERING_DOWN);
+       return err;
 }
 
 int hci_set_powered_sync(struct hci_dev *hdev, u8 val)
index 688890f..3fe6db8 100644 (file)
@@ -1390,6 +1390,14 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
 
        hci_dev_lock(hdev);
 
+       if (!cp->val) {
+               if (hci_dev_test_flag(hdev, HCI_POWERING_DOWN)) {
+                       err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
+                                             MGMT_STATUS_BUSY);
+                       goto failed;
+               }
+       }
+
        if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
                err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
                                      MGMT_STATUS_BUSY);
@@ -9748,6 +9756,9 @@ bool mgmt_powering_down(struct hci_dev *hdev)
        struct mgmt_pending_cmd *cmd;
        struct mgmt_mode *cp;
 
+       if (hci_dev_test_flag(hdev, HCI_POWERING_DOWN))
+               return true;
+
        cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
        if (!cmd)
                return false;
@@ -10055,6 +10066,9 @@ void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
                /* If this is a HCI command related to powering on the
                 * HCI dev don't send any mgmt signals.
                 */
+               if (hci_dev_test_flag(hdev, HCI_POWERING_DOWN))
+                       return;
+
                if (pending_find(MGMT_OP_SET_POWERED, hdev))
                        return;
        }