#define HCI_PAIRING_TIMEOUT    (60000) /* 60 seconds */
 #define HCI_IDLE_TIMEOUT       (6000)  /* 6 seconds */
 #define HCI_INIT_TIMEOUT       (10000) /* 10 seconds */
+#define HCI_CMD_TIMEOUT                (1000)  /* 1 seconds */
 
 /* HCI data types */
 #define HCI_COMMAND_PKT                0x01
 #define HCI_AT_GENERAL_BONDING_MITM    0x05
 
 /* -----  HCI Commands ---- */
+#define HCI_OP_NOP                     0x0000
+
 #define HCI_OP_INQUIRY                 0x0401
 struct hci_cp_inquiry {
        __u8     lap[3];
 
        unsigned int    sco_pkts;
        unsigned int    le_pkts;
 
-       unsigned long   cmd_last_tx;
        unsigned long   acl_last_tx;
        unsigned long   sco_last_tx;
        unsigned long   le_last_tx;
        struct work_struct      power_off;
        struct timer_list       off_timer;
 
+       struct timer_list       cmd_timer;
        struct tasklet_struct   cmd_task;
        struct tasklet_struct   rx_task;
        struct tasklet_struct   tx_task;
 
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/rfkill.h>
+#include <linux/timer.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
 
        /* Drop last sent command */
        if (hdev->sent_cmd) {
+               del_timer_sync(&hdev->cmd_timer);
                kfree_skb(hdev->sent_cmd);
                hdev->sent_cmd = NULL;
        }
        return 0;
 }
 
+/* HCI command timer function */
+static void hci_cmd_timer(unsigned long arg)
+{
+       struct hci_dev *hdev = (void *) arg;
+
+       BT_ERR("%s command tx timeout", hdev->name);
+       atomic_set(&hdev->cmd_cnt, 1);
+       tasklet_schedule(&hdev->cmd_task);
+}
+
 /* Register HCI device */
 int hci_register_dev(struct hci_dev *hdev)
 {
        skb_queue_head_init(&hdev->cmd_q);
        skb_queue_head_init(&hdev->raw_q);
 
+       setup_timer(&hdev->cmd_timer, hci_cmd_timer, (unsigned long) hdev);
+
        for (i = 0; i < NUM_REASSEMBLY; i++)
                hdev->reassembly[i] = NULL;
 
 
        BT_DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt));
 
-       if (!atomic_read(&hdev->cmd_cnt) && time_after(jiffies, hdev->cmd_last_tx + HZ)) {
-               BT_ERR("%s command tx timeout", hdev->name);
-               atomic_set(&hdev->cmd_cnt, 1);
-       }
-
        /* Send queued commands */
        if (atomic_read(&hdev->cmd_cnt)) {
                skb = skb_dequeue(&hdev->cmd_q);
                if (hdev->sent_cmd) {
                        atomic_dec(&hdev->cmd_cnt);
                        hci_send_frame(skb);
-                       hdev->cmd_last_tx = jiffies;
+                       mod_timer(&hdev->cmd_timer,
+                                 jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
                } else {
                        skb_queue_head(&hdev->cmd_q, skb);
                        tasklet_schedule(&hdev->cmd_task);
 
                break;
        }
 
+       if (ev->opcode != HCI_OP_NOP)
+               del_timer(&hdev->cmd_timer);
+
        if (ev->ncmd) {
                atomic_set(&hdev->cmd_cnt, 1);
                if (!skb_queue_empty(&hdev->cmd_q))
                break;
        }
 
+       if (ev->opcode != HCI_OP_NOP)
+               del_timer(&hdev->cmd_timer);
+
        if (ev->ncmd) {
                atomic_set(&hdev->cmd_cnt, 1);
                if (!skb_queue_empty(&hdev->cmd_q))