Skip to content

Commit

Permalink
Bluetooth: Keep MSFT ext info throughout a hci_dev's life cycle
Browse files Browse the repository at this point in the history
This splits the msft_do_{open/close} to msft_do_{open/close} and
msft_{register/unregister}. With this change it is possible to retain
the MSFT extension info irrespective of controller power on/off state.
This helps bluetoothd to report correct 'supported features' of the
controller to the D-Bus clients event if the controller is off. It also
re-reads the MSFT info upon every msft_do_open().

The following test steps were performed.
1. Boot the test device and verify the MSFT support debug log in syslog.
2. Power off the controller and read the 'supported features', power on
   and read again.
3. Restart the bluetoothd and verify the 'supported features' value.

Signed-off-by: Miao-chen Chou <mcchou@chromium.org>
Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Reviewed-by: Archie Pusaka <apusaka@chromium.org>
Reviewed-by: Alain Michaud <alainm@chromium.org>
Signed-off-by: Manish Mandlik <mmandlik@google.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Miao-chen Chou authored and Marcel Holtmann committed Sep 10, 2021
1 parent 9682d36 commit 5031ffc
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 9 deletions.
3 changes: 3 additions & 0 deletions net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3990,6 +3990,7 @@ int hci_register_dev(struct hci_dev *hdev)
queue_work(hdev->req_workqueue, &hdev->power_on);

idr_init(&hdev->adv_monitors_idr);
msft_register(hdev);

return id;

Expand Down Expand Up @@ -4022,6 +4023,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
cancel_work_sync(&hdev->suspend_prepare);
}

msft_unregister(hdev);

hci_dev_do_close(hdev);

if (!test_bit(HCI_INIT, &hdev->flags) &&
Expand Down
55 changes: 46 additions & 9 deletions net/bluetooth/msft.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,28 +184,36 @@ static void reregister_monitor_on_restart(struct hci_dev *hdev, int handle)

void msft_do_open(struct hci_dev *hdev)
{
struct msft_data *msft;
struct msft_data *msft = hdev->msft_data;

if (hdev->msft_opcode == HCI_OP_NOP)
return;

if (!msft) {
bt_dev_err(hdev, "MSFT extension not registered");
return;
}

bt_dev_dbg(hdev, "Initialize MSFT extension");

msft = kzalloc(sizeof(*msft), GFP_KERNEL);
if (!msft)
return;
/* Reset existing MSFT data before re-reading */
kfree(msft->evt_prefix);
msft->evt_prefix = NULL;
msft->evt_prefix_len = 0;
msft->features = 0;

if (!read_supported_features(hdev, msft)) {
hdev->msft_data = NULL;
kfree(msft);
return;
}

INIT_LIST_HEAD(&msft->handle_map);
hdev->msft_data = msft;

if (msft_monitor_supported(hdev)) {
msft->reregistering = true;
msft_set_filter_enable(hdev, true);
/* Monitors get removed on power off, so we need to explicitly
* tell the controller to re-monitor.
*/
reregister_monitor_on_restart(hdev, 0);
}
}
Expand All @@ -221,8 +229,9 @@ void msft_do_close(struct hci_dev *hdev)

bt_dev_dbg(hdev, "Cleanup of MSFT extension");

hdev->msft_data = NULL;

/* The controller will silently remove all monitors on power off.
* Therefore, remove handle_data mapping and reset monitor state.
*/
list_for_each_entry_safe(handle_data, tmp, &msft->handle_map, list) {
monitor = idr_find(&hdev->adv_monitors_idr,
handle_data->mgmt_handle);
Expand All @@ -233,6 +242,34 @@ void msft_do_close(struct hci_dev *hdev)
list_del(&handle_data->list);
kfree(handle_data);
}
}

void msft_register(struct hci_dev *hdev)
{
struct msft_data *msft = NULL;

bt_dev_dbg(hdev, "Register MSFT extension");

msft = kzalloc(sizeof(*msft), GFP_KERNEL);
if (!msft) {
bt_dev_err(hdev, "Failed to register MSFT extension");
return;
}

INIT_LIST_HEAD(&msft->handle_map);
hdev->msft_data = msft;
}

void msft_unregister(struct hci_dev *hdev)
{
struct msft_data *msft = hdev->msft_data;

if (!msft)
return;

bt_dev_dbg(hdev, "Unregister MSFT extension");

hdev->msft_data = NULL;

kfree(msft->evt_prefix);
kfree(msft);
Expand Down
4 changes: 4 additions & 0 deletions net/bluetooth/msft.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#if IS_ENABLED(CONFIG_BT_MSFTEXT)

bool msft_monitor_supported(struct hci_dev *hdev);
void msft_register(struct hci_dev *hdev);
void msft_unregister(struct hci_dev *hdev);
void msft_do_open(struct hci_dev *hdev);
void msft_do_close(struct hci_dev *hdev);
void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb);
Expand All @@ -31,6 +33,8 @@ static inline bool msft_monitor_supported(struct hci_dev *hdev)
return false;
}

static inline void msft_register(struct hci_dev *hdev) {}
static inline void msft_unregister(struct hci_dev *hdev) {}
static inline void msft_do_open(struct hci_dev *hdev) {}
static inline void msft_do_close(struct hci_dev *hdev) {}
static inline void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb) {}
Expand Down

0 comments on commit 5031ffc

Please sign in to comment.