Rename clean_up_hci_state and move to the core header so that we can
power down the controller from within the kernel rather than just via
mgmt commands.

Signed-off-by: Abhishek Pandit-Subedi <abhishekpan...@chromium.org>
Reviewed-by: Daniel Winkler <danielwink...@google.com>
Reviewed-by: Miao-chen Chou <mcc...@chromium.org>
---

 include/net/bluetooth/hci_core.h |  2 ++
 net/bluetooth/hci_core.c         | 45 +++++++++++++++++++++++++++++++
 net/bluetooth/mgmt.c             | 46 +-------------------------------
 3 files changed, 48 insertions(+), 45 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 9873e1c8cd163b..ff32d5a856f17f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1072,6 +1072,8 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, 
__u8 force_active);
 
 void hci_le_conn_failed(struct hci_conn *conn, u8 status);
 
+int hci_clean_up_state(struct hci_dev *hdev);
+
 /*
  * hci_conn_get() and hci_conn_put() are used to control the life-time of an
  * "hci_conn" object. They do not guarantee that the hci_conn object is 
running,
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 502552d6e9aff3..8e90850d6d769e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2290,6 +2290,51 @@ static void hci_power_on(struct work_struct *work)
        }
 }
 
+static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
+{
+       BT_DBG("%s status 0x%02x", hdev->name, status);
+
+       if (hci_conn_count(hdev) == 0) {
+               cancel_delayed_work(&hdev->power_off);
+               queue_work(hdev->req_workqueue, &hdev->power_off.work);
+       }
+}
+
+/* This function requires the caller holds hdev->lock */
+int hci_clean_up_state(struct hci_dev *hdev)
+{
+       struct hci_request req;
+       struct hci_conn *conn;
+       bool discov_stopped;
+       int err;
+       u8 scan = 0x00;
+
+       hci_req_init(&req, hdev);
+
+       if (test_bit(HCI_ISCAN, &hdev->flags) ||
+           test_bit(HCI_PSCAN, &hdev->flags)) {
+               hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+       }
+
+       hci_req_clear_adv_instance(hdev, NULL, NULL, 0x00, false);
+
+       if (hci_dev_test_flag(hdev, HCI_LE_ADV))
+               __hci_req_disable_advertising(&req);
+
+       discov_stopped = hci_req_stop_discovery(&req);
+
+       list_for_each_entry(conn, &hdev->conn_hash.list, list) {
+               /* 0x15 == Terminated due to Power Off */
+               __hci_abort_conn(&req, conn, 0x15);
+       }
+
+       err = hci_req_run(&req, clean_up_hci_complete);
+       if (!err && discov_stopped)
+               hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
+
+       return err;
+}
+
 static void hci_power_off(struct work_struct *work)
 {
        struct hci_dev *hdev = container_of(work, struct hci_dev,
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 12d7b368b428e8..ea136a6b730f9a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1122,16 +1122,6 @@ static int send_settings_rsp(struct sock *sk, u16 
opcode, struct hci_dev *hdev)
                                 sizeof(settings));
 }
 
-static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
-{
-       bt_dev_dbg(hdev, "status 0x%02x", status);
-
-       if (hci_conn_count(hdev) == 0) {
-               cancel_delayed_work(&hdev->power_off);
-               queue_work(hdev->req_workqueue, &hdev->power_off.work);
-       }
-}
-
 void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev, u8 instance)
 {
        struct mgmt_ev_advertising_added ev;
@@ -1159,40 +1149,6 @@ static void cancel_adv_timeout(struct hci_dev *hdev)
        }
 }
 
-static int clean_up_hci_state(struct hci_dev *hdev)
-{
-       struct hci_request req;
-       struct hci_conn *conn;
-       bool discov_stopped;
-       int err;
-
-       hci_req_init(&req, hdev);
-
-       if (test_bit(HCI_ISCAN, &hdev->flags) ||
-           test_bit(HCI_PSCAN, &hdev->flags)) {
-               u8 scan = 0x00;
-               hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
-       }
-
-       hci_req_clear_adv_instance(hdev, NULL, NULL, 0x00, false);
-
-       if (hci_dev_test_flag(hdev, HCI_LE_ADV))
-               __hci_req_disable_advertising(&req);
-
-       discov_stopped = hci_req_stop_discovery(&req);
-
-       list_for_each_entry(conn, &hdev->conn_hash.list, list) {
-               /* 0x15 == Terminated due to Power Off */
-               __hci_abort_conn(&req, conn, 0x15);
-       }
-
-       err = hci_req_run(&req, clean_up_hci_complete);
-       if (!err && discov_stopped)
-               hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
-
-       return err;
-}
-
 static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
                       u16 len)
 {
@@ -1230,7 +1186,7 @@ static int set_powered(struct sock *sk, struct hci_dev 
*hdev, void *data,
                err = 0;
        } else {
                /* Disconnect connections, stop scans, etc */
-               err = clean_up_hci_state(hdev);
+               err = hci_clean_up_state(hdev);
                if (!err)
                        queue_delayed_work(hdev->req_workqueue, 
&hdev->power_off,
                                           HCI_POWER_OFF_TIMEOUT);
-- 
2.29.2.299.gdc1121823c-goog

Reply via email to