netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Marcel Holtmann <marcel@holtmann.org>
To: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>,
	Alain Michaud <alainm@chromium.org>,
	linux-bluetooth@vger.kernel.org,
	chromeos-bluetooth-upstreaming@chromium.org,
	"David S. Miller" <davem@davemloft.net>,
	Johan Hedberg <johan.hedberg@gmail.com>,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	Jakub Kicinski <kuba@kernel.org>
Subject: Re: [RFC PATCH v4 5/5] Bluetooth: Pause discovery and advertising during suspend
Date: Sun, 8 Mar 2020 09:38:59 +0100	[thread overview]
Message-ID: <DB7CF910-5065-45A4-BD4E-A2FDA5B56E67@holtmann.org> (raw)
In-Reply-To: <20200303170610.RFC.v4.5.Iccdad520469ca3524a7e5966c5f88e5bca756e13@changeid>

Hi Abhishek,

> To prevent spurious wake ups, we disable any discovery or advertising
> when we enter suspend and restore it when we exit suspend. While paused,
> we disable any management requests to modify discovery or advertising.
> 
> Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
> ---
> 
> Changes in v4: None
> Changes in v3: None
> Changes in v2:
> * Refactored pause discovery + advertising into its own patch
> 
> include/net/bluetooth/hci_core.h | 11 ++++++++
> net/bluetooth/hci_request.c      | 43 ++++++++++++++++++++++++++++++++
> net/bluetooth/mgmt.c             | 41 ++++++++++++++++++++++++++++++
> 3 files changed, 95 insertions(+)
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 4eb5b2786048..af264a247636 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -91,6 +91,12 @@ struct discovery_state {
> #define SUSPEND_NOTIFIER_TIMEOUT	msecs_to_jiffies(2000) /* 2 seconds */
> 
> enum suspend_tasks {
> +	SUSPEND_PAUSE_DISCOVERY,
> +	SUSPEND_UNPAUSE_DISCOVERY,
> +
> +	SUSPEND_PAUSE_ADVERTISING,
> +	SUSPEND_UNPAUSE_ADVERTISING,
> +
> 	SUSPEND_SCAN_DISABLE,
> 	SUSPEND_SCAN_ENABLE,
> 	SUSPEND_DISCONNECTING,
> @@ -409,6 +415,11 @@ struct hci_dev {
> 
> 	struct discovery_state	discovery;
> 
> +	int			discovery_old_state;
> +	bool			discovery_paused;
> +	int			advertising_old_state;
> +	bool			advertising_paused;
> +
> 	struct notifier_block	suspend_notifier;
> 	struct work_struct	suspend_prepare;
> 	enum suspended_state	suspend_state_next;
> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
> index 88fd95d70f89..e25cfb6fd9aa 100644
> --- a/net/bluetooth/hci_request.c
> +++ b/net/bluetooth/hci_request.c
> @@ -1036,6 +1036,28 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
> 		/* Mark device as suspended */
> 		hdev->suspended = true;
> 
> +		/* Pause discovery if not already stopped */
> +		old_state = hdev->discovery.state;
> +		if (old_state != DISCOVERY_STOPPED) {
> +			set_bit(SUSPEND_PAUSE_DISCOVERY, hdev->suspend_tasks);
> +			hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
> +			queue_work(hdev->req_workqueue, &hdev->discov_update);
> +		}
> +
> +		hdev->discovery_paused = true;
> +		hdev->discovery_old_state = old_state;
> +
> +		/* Stop advertising */
> +		old_state = hci_dev_test_flag(hdev, HCI_ADVERTISING);
> +		if (old_state) {
> +			set_bit(SUSPEND_PAUSE_ADVERTISING, hdev->suspend_tasks);
> +			cancel_delayed_work(&hdev->discov_off);
> +			queue_delayed_work(hdev->req_workqueue,
> +					   &hdev->discov_off, 0);
> +		}
> +
> +		hdev->advertising_paused = true;
> +		hdev->advertising_old_state = old_state;
> 		/* Disable page scan */
> 		page_scan = SCAN_DISABLED;
> 		hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &page_scan);
> @@ -1081,6 +1103,27 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
> 		hci_req_clear_event_filter(&req);
> 		/* Reset passive/background scanning to normal */
> 		hci_req_config_le_suspend_scan(&req);
> +
> +		/* Unpause advertising */
> +		hdev->advertising_paused = false;
> +		if (hdev->advertising_old_state) {
> +			set_bit(SUSPEND_UNPAUSE_ADVERTISING,
> +				hdev->suspend_tasks);
> +			hci_dev_set_flag(hdev, HCI_ADVERTISING);
> +			queue_work(hdev->req_workqueue,
> +				   &hdev->discoverable_update);
> +			hdev->advertising_old_state = 0;
> +		}
> +
> +		/* Unpause discovery */
> +		hdev->discovery_paused = false;
> +		if (hdev->discovery_old_state != DISCOVERY_STOPPED &&
> +		    hdev->discovery_old_state != DISCOVERY_STOPPING) {
> +			set_bit(SUSPEND_UNPAUSE_DISCOVERY, hdev->suspend_tasks);
> +			hci_discovery_set_state(hdev, DISCOVERY_STARTING);
> +			queue_work(hdev->req_workqueue, &hdev->discov_update);
> +		}
> +
> 		hci_req_run(&req, suspend_req_complete);
> 	}
> 
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index f6751ce0d561..28572579c06d 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -1387,6 +1387,12 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
> 		goto failed;
> 	}
> 
> +	if (hdev->advertising_paused) {
> +		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
> +				      MGMT_STATUS_BUSY);
> +		goto failed;
> +	}
> +
> 	if (!hdev_is_powered(hdev)) {
> 		bool changed = false;
> 
> @@ -3870,6 +3876,13 @@ void mgmt_start_discovery_complete(struct hci_dev *hdev, u8 status)
> 	}
> 
> 	hci_dev_unlock(hdev);
> +
> +	/* Handle suspend notifier */
> +	if (test_and_clear_bit(SUSPEND_UNPAUSE_DISCOVERY,
> +			       hdev->suspend_tasks)) {
> +		BT_DBG("Unpaused discovery");
> +		wake_up(&hdev->suspend_wait_q);
> +	}
> }
> 
> static bool discovery_type_is_valid(struct hci_dev *hdev, uint8_t type,
> @@ -3931,6 +3944,13 @@ static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev,
> 		goto failed;
> 	}
> 
> +	/* Can't start discovery when it is paused */
> +	if (hdev->discovery_paused) {
> +		err = mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_BUSY,
> +					&cp->type, sizeof(cp->type));
> +		goto failed;
> +	}
> +
> 	/* Clear the discovery filter first to free any previously
> 	 * allocated memory for the UUID list.
> 	 */
> @@ -4098,6 +4118,12 @@ void mgmt_stop_discovery_complete(struct hci_dev *hdev, u8 status)
> 	}
> 
> 	hci_dev_unlock(hdev);
> +
> +	/* Handle suspend notifier */
> +	if (test_and_clear_bit(SUSPEND_PAUSE_DISCOVERY, hdev->suspend_tasks)) {
> +		BT_DBG("Paused discovery");
> +		wake_up(&hdev->suspend_wait_q);
> +	}
> }
> 
> static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
> @@ -4329,6 +4355,17 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status,
> 	if (match.sk)
> 		sock_put(match.sk);
> 
> +	/* Handle suspend notifier */
> +	if (test_and_clear_bit(SUSPEND_PAUSE_ADVERTISING,
> +			       hdev->suspend_tasks)) {
> +		BT_DBG("Paused advertising");
> +		wake_up(&hdev->suspend_wait_q);
> +	} else if (test_and_clear_bit(SUSPEND_UNPAUSE_ADVERTISING,
> +				      hdev->suspend_tasks)) {
> +		BT_DBG("Unpaused advertising");
> +		wake_up(&hdev->suspend_wait_q);
> +	}
> +
> 	/* If "Set Advertising" was just disabled and instance advertising was
> 	 * set up earlier, then re-enable multi-instance advertising.
> 	 */
> @@ -4380,6 +4417,10 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
> 		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
> 				       MGMT_STATUS_INVALID_PARAMS);
> 
> +	if (hdev->advertising_paused)
> +		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
> +				       MGMT_STATUS_BUSY);
> +
> 	hci_dev_lock(hdev);
> 
> 	val = !!cp->val;

looks good. Just make this 4/5 and use bt_dev_dbg where possible.

Regards

Marcel


      reply	other threads:[~2020-03-08  8:39 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-04  1:06 [RFC PATCH v4 0/5] Bluetooth: Handle system suspend gracefully Abhishek Pandit-Subedi
2020-03-04  1:06 ` [RFC PATCH v4 1/5] Bluetooth: Add mgmt op set_wake_capable Abhishek Pandit-Subedi
2020-03-08  8:28   ` Marcel Holtmann
2020-03-04  1:06 ` [RFC PATCH v4 2/5] Bluetooth: Handle PM_SUSPEND_PREPARE and PM_POST_SUSPEND Abhishek Pandit-Subedi
2020-03-08  8:28   ` Marcel Holtmann
2020-03-04  1:06 ` [RFC PATCH v4 3/5] Bluetooth: Handle BR/EDR devices during suspend Abhishek Pandit-Subedi
2020-03-08  8:30   ` Marcel Holtmann
2020-03-04  1:06 ` [RFC PATCH v4 4/5] Bluetooth: Handle LE " Abhishek Pandit-Subedi
2020-03-08  8:37   ` Marcel Holtmann
2020-03-04  1:06 ` [RFC PATCH v4 5/5] Bluetooth: Pause discovery and advertising " Abhishek Pandit-Subedi
2020-03-08  8:38   ` Marcel Holtmann [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DB7CF910-5065-45A4-BD4E-A2FDA5B56E67@holtmann.org \
    --to=marcel@holtmann.org \
    --cc=abhishekpandit@chromium.org \
    --cc=alainm@chromium.org \
    --cc=chromeos-bluetooth-upstreaming@chromium.org \
    --cc=davem@davemloft.net \
    --cc=johan.hedberg@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luiz.dentz@gmail.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).