summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2021-10-05 18:09:33 -0700
committerMarcel Holtmann <marcel@holtmann.org>2021-10-06 10:48:34 +0200
commitd16e6d19ccc6d3aa6b96d6a8fdb9e04fb9dffdbd (patch)
treeec08e326a89a1698eb6356ac524ed5802277ed5f
parentd0f1c248b4ff71cada1b9e4ed61a1992cd94c3df (diff)
Bluetooth: hci_vhci: Fix calling hci_{suspend,resume}_dev
Defer calls to hci_{suspend,resume}_dev to work so it doesn't block the processing of the events. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--drivers/bluetooth/hci_vhci.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index b45db0db347c..20f8ce995555 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -38,6 +38,7 @@ struct vhci_data {
struct mutex open_mutex;
struct delayed_work open_timeout;
+ struct work_struct suspend_work;
bool suspended;
bool wakeup;
@@ -114,6 +115,17 @@ static ssize_t force_suspend_read(struct file *file, char __user *user_buf,
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
+static void vhci_suspend_work(struct work_struct *work)
+{
+ struct vhci_data *data = container_of(work, struct vhci_data,
+ suspend_work);
+
+ if (data->suspended)
+ hci_suspend_dev(data->hdev);
+ else
+ hci_resume_dev(data->hdev);
+}
+
static ssize_t force_suspend_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
@@ -129,16 +141,10 @@ static ssize_t force_suspend_write(struct file *file,
if (data->suspended == enable)
return -EALREADY;
- if (enable)
- err = hci_suspend_dev(data->hdev);
- else
- err = hci_resume_dev(data->hdev);
-
- if (err)
- return err;
-
data->suspended = enable;
+ schedule_work(&data->suspend_work);
+
return count;
}
@@ -440,6 +446,7 @@ static int vhci_open(struct inode *inode, struct file *file)
mutex_init(&data->open_mutex);
INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);
+ INIT_WORK(&data->suspend_work, vhci_suspend_work);
file->private_data = data;
nonseekable_open(inode, file);
@@ -455,6 +462,7 @@ static int vhci_release(struct inode *inode, struct file *file)
struct hci_dev *hdev;
cancel_delayed_work_sync(&data->open_timeout);
+ flush_work(&data->suspend_work);
hdev = data->hdev;