Commit 40b87657 authored by Heitor Alves de Siqueira's avatar Heitor Alves de Siqueira Committed by Luiz Augusto von Dentz
Browse files

Bluetooth: hci_core: Rework hci_dev_do_reset() to use hci_sync functions



The current HCI reset function in hci_core.c duplicates most of the work
done by hci_dev_close_sync(), and doesn't handle LE, advertising or
discovery.

Instead of porting these to hci_dev_do_reset(), directly call the
close/open functions from hci_sync to reset the hdev. MGMT now notifies
when a user performs a reset.

Suggested-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: default avatarHeitor Alves de Siqueira <halves@igalia.com>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 4b5f8e60
Loading
Loading
Loading
Loading
+3 −40
Original line number Diff line number Diff line
@@ -539,46 +539,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev)

	hci_req_sync_lock(hdev);

	/* Drop queues */
	skb_queue_purge(&hdev->rx_q);
	skb_queue_purge(&hdev->cmd_q);

	/* Cancel these to avoid queueing non-chained pending work */
	hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
	/* Wait for
	 *
	 *    if (!hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE))
	 *        queue_delayed_work(&hdev->{cmd,ncmd}_timer)
	 *
	 * inside RCU section to see the flag or complete scheduling.
	 */
	synchronize_rcu();
	/* Explicitly cancel works in case scheduled after setting the flag. */
	cancel_delayed_work(&hdev->cmd_timer);
	cancel_delayed_work(&hdev->ncmd_timer);

	/* Avoid potential lockdep warnings from the *_flush() calls by
	 * ensuring the workqueue is empty up front.
	 */
	drain_workqueue(hdev->workqueue);

	hci_dev_lock(hdev);
	hci_inquiry_cache_flush(hdev);
	hci_conn_hash_flush(hdev);
	hci_dev_unlock(hdev);

	if (hdev->flush)
		hdev->flush(hdev);

	hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);

	atomic_set(&hdev->cmd_cnt, 1);
	hdev->acl_cnt = 0;
	hdev->sco_cnt = 0;
	hdev->le_cnt = 0;
	hdev->iso_cnt = 0;

	ret = hci_reset_sync(hdev);
	ret = hci_dev_close_sync(hdev);
	if (!ret)
		ret = hci_dev_open_sync(hdev);

	hci_req_sync_unlock(hdev);
	return ret;