diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2015-01-30 03:58:54 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-01-30 05:03:19 -0500 |
commit | a087a98e0767cf6c4f2480e6de5441497c9ba5b7 (patch) | |
tree | cff12cae86d3e8b4633d65b57b334c9b9885ebd7 /drivers/bluetooth | |
parent | 74d9daafa5e0b4f9183540b41b337d42662f537b (diff) |
Bluetooth: btusb: Fix race when waiting for BTUSB_DOWNLOADING
The test for BTUSB_DOWNLOADING must be after adding to the wait queue
and setting the TASK_INTERRUPTIBLE state. Otherwise the flag may get
cleared after we test for it and we end up getting a timeout since
schedule_timeout() waits for the full duration. This patch uses a
wait_on_bit_timeout() + wake_up_bit(). To perform the task both
race-free as well as in a much simpler way.
Since there's no global wait_on_bit_timeout() helper yet (even though
all the building blocks for it are in place) this patch creates a
temporary local btusb copy of it until the global one has made it to
upstream trees.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r-- | drivers/bluetooth/btusb.c | 67 |
1 files changed, 34 insertions, 33 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 86f3d92de22a..98341a463f30 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -334,6 +334,16 @@ struct btusb_data { | |||
334 | int (*recv_bulk)(struct btusb_data *data, void *buffer, int count); | 334 | int (*recv_bulk)(struct btusb_data *data, void *buffer, int count); |
335 | }; | 335 | }; |
336 | 336 | ||
337 | static int btusb_wait_on_bit_timeout(void *word, int bit, unsigned long timeout, | ||
338 | unsigned mode) | ||
339 | { | ||
340 | might_sleep(); | ||
341 | if (!test_bit(bit, word)) | ||
342 | return 0; | ||
343 | return out_of_line_wait_on_bit_timeout(word, bit, bit_wait_timeout, | ||
344 | mode, timeout); | ||
345 | } | ||
346 | |||
337 | static inline void btusb_free_frags(struct btusb_data *data) | 347 | static inline void btusb_free_frags(struct btusb_data *data) |
338 | { | 348 | { |
339 | unsigned long flags; | 349 | unsigned long flags; |
@@ -1800,8 +1810,10 @@ static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) | |||
1800 | 1810 | ||
1801 | if (test_and_clear_bit(BTUSB_DOWNLOADING, | 1811 | if (test_and_clear_bit(BTUSB_DOWNLOADING, |
1802 | &data->flags) && | 1812 | &data->flags) && |
1803 | test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) | 1813 | test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) { |
1804 | wake_up_interruptible(&hdev->req_wait_q); | 1814 | smp_mb__after_atomic(); |
1815 | wake_up_bit(&data->flags, BTUSB_DOWNLOADING); | ||
1816 | } | ||
1805 | } | 1817 | } |
1806 | 1818 | ||
1807 | /* When switching to the operational firmware the device | 1819 | /* When switching to the operational firmware the device |
@@ -2165,43 +2177,32 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) | |||
2165 | 2177 | ||
2166 | set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); | 2178 | set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); |
2167 | 2179 | ||
2180 | BT_INFO("%s: Waiting for firmware download to complete", hdev->name); | ||
2181 | |||
2168 | /* Before switching the device into operational mode and with that | 2182 | /* Before switching the device into operational mode and with that |
2169 | * booting the loaded firmware, wait for the bootloader notification | 2183 | * booting the loaded firmware, wait for the bootloader notification |
2170 | * that all fragments have been successfully received. | 2184 | * that all fragments have been successfully received. |
2171 | * | 2185 | * |
2172 | * When the event processing receives the notification, then this | 2186 | * When the event processing receives the notification, then the |
2173 | * flag will be cleared. So just in case that happens really quickly, | 2187 | * BTUSB_DOWNLOADING flag will be cleared. |
2174 | * check it first before adding the wait queue. | 2188 | * |
2189 | * The firmware loading should not take longer than 5 seconds | ||
2190 | * and thus just timeout if that happens and fail the setup | ||
2191 | * of this device. | ||
2175 | */ | 2192 | */ |
2176 | if (test_bit(BTUSB_DOWNLOADING, &data->flags)) { | 2193 | err = btusb_wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING, |
2177 | DECLARE_WAITQUEUE(wait, current); | 2194 | msecs_to_jiffies(5000), |
2178 | signed long timeout; | 2195 | TASK_INTERRUPTIBLE); |
2179 | 2196 | if (err == 1) { | |
2180 | BT_INFO("%s: Waiting for firmware download to complete", | 2197 | BT_ERR("%s: Firmware loading interrupted", hdev->name); |
2181 | hdev->name); | 2198 | err = -EINTR; |
2182 | 2199 | goto done; | |
2183 | add_wait_queue(&hdev->req_wait_q, &wait); | 2200 | } |
2184 | set_current_state(TASK_INTERRUPTIBLE); | ||
2185 | |||
2186 | /* The firmware loading should not take longer than 5 seconds | ||
2187 | * and thus just timeout if that happens and fail the setup | ||
2188 | * of this device. | ||
2189 | */ | ||
2190 | timeout = schedule_timeout(msecs_to_jiffies(5000)); | ||
2191 | |||
2192 | remove_wait_queue(&hdev->req_wait_q, &wait); | ||
2193 | |||
2194 | if (signal_pending(current)) { | ||
2195 | BT_ERR("%s: Firmware loading interrupted", hdev->name); | ||
2196 | err = -EINTR; | ||
2197 | goto done; | ||
2198 | } | ||
2199 | 2201 | ||
2200 | if (!timeout) { | 2202 | if (err) { |
2201 | BT_ERR("%s: Firmware loading timeout", hdev->name); | 2203 | BT_ERR("%s: Firmware loading timeout", hdev->name); |
2202 | err = -ETIMEDOUT; | 2204 | err = -ETIMEDOUT; |
2203 | goto done; | 2205 | goto done; |
2204 | } | ||
2205 | } | 2206 | } |
2206 | 2207 | ||
2207 | if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) { | 2208 | if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) { |