aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorVille Tervo <ville.tervo@nokia.com>2011-02-16 09:32:41 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-02-16 14:33:26 -0500
commit6bd32326cdaa9b14794416150c88e4832fb7e592 (patch)
tree4c48387761df0207bb50952dda7fd5c980893351 /net/bluetooth
parent7f4b2b04c88377af30c022f36c060190182850fb (diff)
Bluetooth: Use proper timer for hci command timout
Use proper timer instead of hci command flow control to timeout failed hci commands. Otherwise stack ends up sending commands when flow control is used to block new commands. 2010-09-01 18:29:41.592132 < HCI Command: Remote Name Request (0x01|0x0019) plen 10 bdaddr 00:16:CF:E1:C7:D7 mode 2 clkoffset 0x0000 2010-09-01 18:29:41.592681 > HCI Event: Command Status (0x0f) plen 4 Remote Name Request (0x01|0x0019) status 0x00 ncmd 0 2010-09-01 18:29:51.022033 < HCI Command: Remote Name Request Cancel (0x01|0x001a) plen 6 bdaddr 00:16:CF:E1:C7:D7 Signed-off-by: Ville Tervo <ville.tervo@nokia.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_core.c22
-rw-r--r--net/bluetooth/hci_event.c6
2 files changed, 22 insertions, 6 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c01415bc8946..702d5651c656 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -41,6 +41,7 @@
41#include <linux/interrupt.h> 41#include <linux/interrupt.h>
42#include <linux/notifier.h> 42#include <linux/notifier.h>
43#include <linux/rfkill.h> 43#include <linux/rfkill.h>
44#include <linux/timer.h>
44#include <net/sock.h> 45#include <net/sock.h>
45 46
46#include <asm/system.h> 47#include <asm/system.h>
@@ -623,6 +624,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
623 624
624 /* Drop last sent command */ 625 /* Drop last sent command */
625 if (hdev->sent_cmd) { 626 if (hdev->sent_cmd) {
627 del_timer_sync(&hdev->cmd_timer);
626 kfree_skb(hdev->sent_cmd); 628 kfree_skb(hdev->sent_cmd);
627 hdev->sent_cmd = NULL; 629 hdev->sent_cmd = NULL;
628 } 630 }
@@ -1066,6 +1068,16 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
1066 return 0; 1068 return 0;
1067} 1069}
1068 1070
1071/* HCI command timer function */
1072static void hci_cmd_timer(unsigned long arg)
1073{
1074 struct hci_dev *hdev = (void *) arg;
1075
1076 BT_ERR("%s command tx timeout", hdev->name);
1077 atomic_set(&hdev->cmd_cnt, 1);
1078 tasklet_schedule(&hdev->cmd_task);
1079}
1080
1069/* Register HCI device */ 1081/* Register HCI device */
1070int hci_register_dev(struct hci_dev *hdev) 1082int hci_register_dev(struct hci_dev *hdev)
1071{ 1083{
@@ -1112,6 +1124,8 @@ int hci_register_dev(struct hci_dev *hdev)
1112 skb_queue_head_init(&hdev->cmd_q); 1124 skb_queue_head_init(&hdev->cmd_q);
1113 skb_queue_head_init(&hdev->raw_q); 1125 skb_queue_head_init(&hdev->raw_q);
1114 1126
1127 setup_timer(&hdev->cmd_timer, hci_cmd_timer, (unsigned long) hdev);
1128
1115 for (i = 0; i < NUM_REASSEMBLY; i++) 1129 for (i = 0; i < NUM_REASSEMBLY; i++)
1116 hdev->reassembly[i] = NULL; 1130 hdev->reassembly[i] = NULL;
1117 1131
@@ -2004,11 +2018,6 @@ static void hci_cmd_task(unsigned long arg)
2004 2018
2005 BT_DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt)); 2019 BT_DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt));
2006 2020
2007 if (!atomic_read(&hdev->cmd_cnt) && time_after(jiffies, hdev->cmd_last_tx + HZ)) {
2008 BT_ERR("%s command tx timeout", hdev->name);
2009 atomic_set(&hdev->cmd_cnt, 1);
2010 }
2011
2012 /* Send queued commands */ 2021 /* Send queued commands */
2013 if (atomic_read(&hdev->cmd_cnt)) { 2022 if (atomic_read(&hdev->cmd_cnt)) {
2014 skb = skb_dequeue(&hdev->cmd_q); 2023 skb = skb_dequeue(&hdev->cmd_q);
@@ -2021,7 +2030,8 @@ static void hci_cmd_task(unsigned long arg)
2021 if (hdev->sent_cmd) { 2030 if (hdev->sent_cmd) {
2022 atomic_dec(&hdev->cmd_cnt); 2031 atomic_dec(&hdev->cmd_cnt);
2023 hci_send_frame(skb); 2032 hci_send_frame(skb);
2024 hdev->cmd_last_tx = jiffies; 2033 mod_timer(&hdev->cmd_timer,
2034 jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
2025 } else { 2035 } else {
2026 skb_queue_head(&hdev->cmd_q, skb); 2036 skb_queue_head(&hdev->cmd_q, skb);
2027 tasklet_schedule(&hdev->cmd_task); 2037 tasklet_schedule(&hdev->cmd_task);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 74f04a27734d..09cb29e8713a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1732,6 +1732,9 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
1732 break; 1732 break;
1733 } 1733 }
1734 1734
1735 if (ev->opcode != HCI_OP_NOP)
1736 del_timer(&hdev->cmd_timer);
1737
1735 if (ev->ncmd) { 1738 if (ev->ncmd) {
1736 atomic_set(&hdev->cmd_cnt, 1); 1739 atomic_set(&hdev->cmd_cnt, 1);
1737 if (!skb_queue_empty(&hdev->cmd_q)) 1740 if (!skb_queue_empty(&hdev->cmd_q))
@@ -1807,6 +1810,9 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1807 break; 1810 break;
1808 } 1811 }
1809 1812
1813 if (ev->opcode != HCI_OP_NOP)
1814 del_timer(&hdev->cmd_timer);
1815
1810 if (ev->ncmd) { 1816 if (ev->ncmd) {
1811 atomic_set(&hdev->cmd_cnt, 1); 1817 atomic_set(&hdev->cmd_cnt, 1);
1812 if (!skb_queue_empty(&hdev->cmd_q)) 1818 if (!skb_queue_empty(&hdev->cmd_q))