[PATCH] Bluetooth: Add counter for not acked HCI commands

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Adds counter for HCI commands which were sent but are not yet acked.
This is to prevent race conditions in scenarios where HCI commands
are sent between complete event and command status event, i.e.
last sent HCI command is not accounted in credits number returned
by command status event.

< HCI Command: Create Connection (0x01|0x0005) plen 13
    bdaddr 00:23:76:E3:24:58 ptype 0xcc18 rswitch 0x01 clkoffset 0x0000
    Packet type: DM1 DM3 DM5 DH1 DH3 DH5
> HCI Event: Command Status (0x0f) plen 4
    Create Connection (0x01|0x0005) status 0x00 ncmd 1
> HCI Event: Connect Complete (0x03) plen 11
    status 0x00 handle 1 bdaddr 00:23:76:E3:24:58 type ACL encrypt 0x00
< HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2
    handle 1
> HCI Event: Command Status (0x0f) plen 4
    Unknown (0x00|0x0000) status 0x00 ncmd 2
> HCI Event: Command Status (0x0f) plen 4
    Read Remote Supported Features (0x01|0x001b) status 0x00 ncmd 1
> HCI Event: Max Slots Change (0x1b) plen 3
    handle 1 slots 5
> HCI Event: Read Remote Supported Features (0x0b) plen 11
    status 0x00 handle 1
    Features: 0xbf 0xfe 0x8f 0xfe 0x9b 0xff 0x79 0x83
< HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3
    handle 1 page 1
> HCI Event: Command Status (0x0f) plen 4
    Unknown (0x00|0x0000) status 0x00 ncmd 2
> HCI Event: Command Status (0x0f) plen 4
    Read Remote Extended Features (0x01|0x001c) status 0x00 ncmd 1
> HCI Event: Read Remote Extended Features (0x23) plen 13
    status 0x00 handle 1 page 1 max 1
    Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
< HCI Command: Authentication Requested (0x01|0x0011) plen 2
    handle 1
> HCI Event: Command Status (0x0f) plen 4
    Unknown (0x00|0x0000) status 0x00 ncmd 2
< HCI Command: Remote Name Request (0x01|0x0019) plen 10
    bdaddr 00:23:76:E3:24:58 mode 2 clkoffset 0x0000
> HCI Event: Command Status (0x0f) plen 4
    Authentication Requested (0x01|0x0011) status 0x00 ncmd 1
> HCI Event: Link Key Request (0x17) plen 6
    bdaddr 00:23:76:E3:24:58

Following command should not be sent here since we have effectively no
credits for HCI command, i.e. 1 credit returned by CS for Authentication
Requested was already consumed by Remote Name Request.

< HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6
    bdaddr 00:23:76:E3:24:58
> HCI Event: Command Status (0x0f) plen 4
    Remote Name Request (0x01|0x0019) status 0x00 ncmd 0
> HCI Event: Command Complete (0x0e) plen 10
    Link Key Request Negative Reply (0x01|0x000c) ncmd 0
    status 0x0c bdaddr 00:23:76:E3:24:58
    Error: Command Disallowed

Signed-off-by: Andrzej Kaczmarek <andrzej.kaczmarek@xxxxxxxxx>
---
 include/net/bluetooth/hci_core.h |    1 +
 net/bluetooth/hci_core.c         |   10 ++++++++--
 net/bluetooth/hci_event.c        |    8 ++++++--
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 441dadb..baf190b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -121,6 +121,7 @@ struct hci_dev {
 	unsigned long	quirks;
 
 	atomic_t	cmd_cnt;
+	atomic_t	cmd_not_ack;
 	unsigned int	acl_cnt;
 	unsigned int	sco_cnt;
 	unsigned int	le_cnt;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b372fb8..1c6886d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -531,6 +531,7 @@ int hci_dev_open(__u16 dev)
 
 	if (!test_bit(HCI_RAW, &hdev->flags)) {
 		atomic_set(&hdev->cmd_cnt, 1);
+		atomic_set(&hdev->cmd_not_ack, 0);
 		set_bit(HCI_INIT, &hdev->flags);
 		hdev->init_last_cmd = 0;
 
@@ -606,6 +607,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 	/* Reset device */
 	skb_queue_purge(&hdev->cmd_q);
 	atomic_set(&hdev->cmd_cnt, 1);
+	atomic_set(&hdev->cmd_not_ack, 0);
 	if (!test_bit(HCI_RAW, &hdev->flags)) {
 		set_bit(HCI_INIT, &hdev->flags);
 		__hci_request(hdev, hci_reset_req, 0,
@@ -684,6 +686,7 @@ int hci_dev_reset(__u16 dev)
 		hdev->flush(hdev);
 
 	atomic_set(&hdev->cmd_cnt, 1);
+	atomic_set(&hdev->cmd_not_ack, 0);
 	hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0;
 
 	if (!test_bit(HCI_RAW, &hdev->flags))
@@ -1074,6 +1077,7 @@ static void hci_cmd_timer(unsigned long arg)
 
 	BT_ERR("%s command tx timeout", hdev->name);
 	atomic_set(&hdev->cmd_cnt, 1);
+	atomic_add_unless(&hdev->cmd_not_ack, -1, 0);
 	tasklet_schedule(&hdev->cmd_task);
 }
 
@@ -2015,10 +2019,11 @@ static void hci_cmd_task(unsigned long arg)
 	struct hci_dev *hdev = (struct hci_dev *) arg;
 	struct sk_buff *skb;
 
-	BT_DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt));
+	BT_DBG("%s cnt %d not_ack %d", hdev->name, atomic_read(&hdev->cmd_cnt),
+					atomic_read(&hdev->cmd_not_ack));
 
 	/* Send queued commands */
-	if (atomic_read(&hdev->cmd_cnt)) {
+	if (atomic_read(&hdev->cmd_cnt) > atomic_read(&hdev->cmd_not_ack)) {
 		skb = skb_dequeue(&hdev->cmd_q);
 		if (!skb)
 			return;
@@ -2028,6 +2033,7 @@ static void hci_cmd_task(unsigned long arg)
 		hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC);
 		if (hdev->sent_cmd) {
 			atomic_dec(&hdev->cmd_cnt);
+			atomic_inc(&hdev->cmd_not_ack);
 			hci_send_frame(skb);
 			mod_timer(&hdev->cmd_timer,
 				  jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3fbfa50..3cf63a1 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1766,8 +1766,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		break;
 	}
 
-	if (ev->opcode != HCI_OP_NOP)
+	if (ev->opcode != HCI_OP_NOP) {
 		del_timer(&hdev->cmd_timer);
+		atomic_add_unless(&hdev->cmd_not_ack, -1, 0);
+	}
 
 	if (ev->ncmd) {
 		atomic_set(&hdev->cmd_cnt, 1);
@@ -1844,8 +1846,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		break;
 	}
 
-	if (ev->opcode != HCI_OP_NOP)
+	if (ev->opcode != HCI_OP_NOP) {
 		del_timer(&hdev->cmd_timer);
+		atomic_add_unless(&hdev->cmd_not_ack, -1, 0);
+	}
 
 	if (ev->ncmd) {
 		atomic_set(&hdev->cmd_cnt, 1);
-- 
1.7.0.4

Patch on behalf of ST-Ericsson
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux