diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2013-01-14 15:33:50 -0500 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2013-01-17 23:54:21 -0500 |
commit | 6ead1bbc381a674c20f227dbe6f3a8c6f67ce7a2 (patch) | |
tree | d7b1a11d2a20c8d36bb9ce39467cecbc7735a640 /net/bluetooth | |
parent | 52e0b011e29f36bc5c02ea3adbf4d864a38373de (diff) |
Bluetooth: Add a new workqueue for hci_request operations
The hci_request function is blocking and cannot be called through the
usual per-HCI device workqueue (hdev->workqueue). While hci_request is
in progress any other work from the queue, including sending HCI
commands to the controller would be blocked and eventually cause the
hci_request call to time out.
This patch adds a second workqueue to be used by operations needing
hci_request and thereby avoiding issues with blocking other workqueue
users.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_core.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 596660d37c5e..f73907aad79f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1799,6 +1799,15 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1799 | goto err; | 1799 | goto err; |
1800 | } | 1800 | } |
1801 | 1801 | ||
1802 | hdev->req_workqueue = alloc_workqueue(hdev->name, | ||
1803 | WQ_HIGHPRI | WQ_UNBOUND | | ||
1804 | WQ_MEM_RECLAIM, 1); | ||
1805 | if (!hdev->req_workqueue) { | ||
1806 | destroy_workqueue(hdev->workqueue); | ||
1807 | error = -ENOMEM; | ||
1808 | goto err; | ||
1809 | } | ||
1810 | |||
1802 | error = hci_add_sysfs(hdev); | 1811 | error = hci_add_sysfs(hdev); |
1803 | if (error < 0) | 1812 | if (error < 0) |
1804 | goto err_wqueue; | 1813 | goto err_wqueue; |
@@ -1827,6 +1836,7 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1827 | 1836 | ||
1828 | err_wqueue: | 1837 | err_wqueue: |
1829 | destroy_workqueue(hdev->workqueue); | 1838 | destroy_workqueue(hdev->workqueue); |
1839 | destroy_workqueue(hdev->req_workqueue); | ||
1830 | err: | 1840 | err: |
1831 | ida_simple_remove(&hci_index_ida, hdev->id); | 1841 | ida_simple_remove(&hci_index_ida, hdev->id); |
1832 | write_lock(&hci_dev_list_lock); | 1842 | write_lock(&hci_dev_list_lock); |
@@ -1880,6 +1890,7 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
1880 | hci_del_sysfs(hdev); | 1890 | hci_del_sysfs(hdev); |
1881 | 1891 | ||
1882 | destroy_workqueue(hdev->workqueue); | 1892 | destroy_workqueue(hdev->workqueue); |
1893 | destroy_workqueue(hdev->req_workqueue); | ||
1883 | 1894 | ||
1884 | hci_dev_lock(hdev); | 1895 | hci_dev_lock(hdev); |
1885 | hci_blacklist_clear(hdev); | 1896 | hci_blacklist_clear(hdev); |