diff options
-rw-r--r-- | drivers/bluetooth/hci_h5.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index f9067ce25568..831ccfecc8a9 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c | |||
@@ -33,7 +33,8 @@ | |||
33 | #define HCI_3WIRE_ACK_PKT 0 | 33 | #define HCI_3WIRE_ACK_PKT 0 |
34 | #define HCI_3WIRE_LINK_PKT 15 | 34 | #define HCI_3WIRE_LINK_PKT 15 |
35 | 35 | ||
36 | #define H5_TXWINSIZE 4 | 36 | /* Sliding window size */ |
37 | #define H5_TX_WIN_MAX 4 | ||
37 | 38 | ||
38 | #define H5_ACK_TIMEOUT msecs_to_jiffies(250) | 39 | #define H5_ACK_TIMEOUT msecs_to_jiffies(250) |
39 | #define H5_SYNC_TIMEOUT msecs_to_jiffies(100) | 40 | #define H5_SYNC_TIMEOUT msecs_to_jiffies(100) |
@@ -74,6 +75,7 @@ struct h5 { | |||
74 | bool tx_ack_req; /* Pending ack to send */ | 75 | bool tx_ack_req; /* Pending ack to send */ |
75 | u8 tx_seq; /* Next seq number to send */ | 76 | u8 tx_seq; /* Next seq number to send */ |
76 | u8 tx_ack; /* Next ack number to send */ | 77 | u8 tx_ack; /* Next ack number to send */ |
78 | u8 tx_win; /* Sliding window size */ | ||
77 | 79 | ||
78 | enum { | 80 | enum { |
79 | H5_UNINITIALIZED, | 81 | H5_UNINITIALIZED, |
@@ -106,10 +108,20 @@ static void h5_link_control(struct hci_uart *hu, const void *data, size_t len) | |||
106 | skb_queue_tail(&h5->unrel, nskb); | 108 | skb_queue_tail(&h5->unrel, nskb); |
107 | } | 109 | } |
108 | 110 | ||
111 | static u8 h5_cfg_field(struct h5 *h5) | ||
112 | { | ||
113 | u8 field = 0; | ||
114 | |||
115 | /* Sliding window size (first 3 bits) */ | ||
116 | field |= (h5->tx_win & 7); | ||
117 | |||
118 | return field; | ||
119 | } | ||
120 | |||
109 | static void h5_timed_event(unsigned long arg) | 121 | static void h5_timed_event(unsigned long arg) |
110 | { | 122 | { |
111 | const unsigned char sync_req[] = { 0x01, 0x7e }; | 123 | const unsigned char sync_req[] = { 0x01, 0x7e }; |
112 | const unsigned char conf_req[] = { 0x03, 0xfc, 0x01 }; | 124 | unsigned char conf_req[] = { 0x03, 0xfc, 0x01 }; |
113 | struct hci_uart *hu = (struct hci_uart *) arg; | 125 | struct hci_uart *hu = (struct hci_uart *) arg; |
114 | struct h5 *h5 = hu->priv; | 126 | struct h5 *h5 = hu->priv; |
115 | struct sk_buff *skb; | 127 | struct sk_buff *skb; |
@@ -120,8 +132,10 @@ static void h5_timed_event(unsigned long arg) | |||
120 | if (h5->state == H5_UNINITIALIZED) | 132 | if (h5->state == H5_UNINITIALIZED) |
121 | h5_link_control(hu, sync_req, sizeof(sync_req)); | 133 | h5_link_control(hu, sync_req, sizeof(sync_req)); |
122 | 134 | ||
123 | if (h5->state == H5_INITIALIZED) | 135 | if (h5->state == H5_INITIALIZED) { |
136 | conf_req[2] = h5_cfg_field(h5); | ||
124 | h5_link_control(hu, conf_req, sizeof(conf_req)); | 137 | h5_link_control(hu, conf_req, sizeof(conf_req)); |
138 | } | ||
125 | 139 | ||
126 | if (h5->state != H5_ACTIVE) { | 140 | if (h5->state != H5_ACTIVE) { |
127 | mod_timer(&h5->timer, jiffies + H5_SYNC_TIMEOUT); | 141 | mod_timer(&h5->timer, jiffies + H5_SYNC_TIMEOUT); |
@@ -171,6 +185,8 @@ static int h5_open(struct hci_uart *hu) | |||
171 | h5->timer.function = h5_timed_event; | 185 | h5->timer.function = h5_timed_event; |
172 | h5->timer.data = (unsigned long) hu; | 186 | h5->timer.data = (unsigned long) hu; |
173 | 187 | ||
188 | h5->tx_win = H5_TX_WIN_MAX; | ||
189 | |||
174 | set_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags); | 190 | set_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags); |
175 | 191 | ||
176 | /* Send initial sync request */ | 192 | /* Send initial sync request */ |
@@ -242,8 +258,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) | |||
242 | struct h5 *h5 = hu->priv; | 258 | struct h5 *h5 = hu->priv; |
243 | const unsigned char sync_req[] = { 0x01, 0x7e }; | 259 | const unsigned char sync_req[] = { 0x01, 0x7e }; |
244 | const unsigned char sync_rsp[] = { 0x02, 0x7d }; | 260 | const unsigned char sync_rsp[] = { 0x02, 0x7d }; |
245 | const unsigned char conf_req[] = { 0x03, 0xfc, 0x01 }; | 261 | unsigned char conf_req[] = { 0x03, 0xfc, 0x01 }; |
246 | const unsigned char conf_rsp[] = { 0x04, 0x7b, 0x01 }; | 262 | const unsigned char conf_rsp[] = { 0x04, 0x7b }; |
247 | const unsigned char wakeup_req[] = { 0x05, 0xfa }; | 263 | const unsigned char wakeup_req[] = { 0x05, 0xfa }; |
248 | const unsigned char woken_req[] = { 0x06, 0xf9 }; | 264 | const unsigned char woken_req[] = { 0x06, 0xf9 }; |
249 | const unsigned char sleep_req[] = { 0x07, 0x78 }; | 265 | const unsigned char sleep_req[] = { 0x07, 0x78 }; |
@@ -258,6 +274,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) | |||
258 | if (H5_HDR_LEN(hdr) < 2) | 274 | if (H5_HDR_LEN(hdr) < 2) |
259 | return; | 275 | return; |
260 | 276 | ||
277 | conf_req[2] = h5_cfg_field(h5); | ||
278 | |||
261 | if (memcmp(data, sync_req, 2) == 0) { | 279 | if (memcmp(data, sync_req, 2) == 0) { |
262 | h5_link_control(hu, sync_rsp, 2); | 280 | h5_link_control(hu, sync_rsp, 2); |
263 | } else if (memcmp(data, sync_rsp, 2) == 0) { | 281 | } else if (memcmp(data, sync_rsp, 2) == 0) { |
@@ -267,7 +285,9 @@ static void h5_handle_internal_rx(struct hci_uart *hu) | |||
267 | h5_link_control(hu, conf_rsp, 2); | 285 | h5_link_control(hu, conf_rsp, 2); |
268 | h5_link_control(hu, conf_req, 3); | 286 | h5_link_control(hu, conf_req, 3); |
269 | } else if (memcmp(data, conf_rsp, 2) == 0) { | 287 | } else if (memcmp(data, conf_rsp, 2) == 0) { |
270 | BT_DBG("Three-wire init sequence complete"); | 288 | if (H5_HDR_LEN(hdr) > 2) |
289 | h5->tx_win = (data[2] & 7); | ||
290 | BT_DBG("Three-wire init complete. tx_win %u", h5->tx_win); | ||
271 | h5->state = H5_ACTIVE; | 291 | h5->state = H5_ACTIVE; |
272 | hci_uart_init_ready(hu); | 292 | hci_uart_init_ready(hu); |
273 | return; | 293 | return; |
@@ -663,7 +683,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu) | |||
663 | 683 | ||
664 | spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING); | 684 | spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING); |
665 | 685 | ||
666 | if (h5->unack.qlen >= H5_TXWINSIZE) | 686 | if (h5->unack.qlen >= h5->tx_win) |
667 | goto unlock; | 687 | goto unlock; |
668 | 688 | ||
669 | if ((skb = skb_dequeue(&h5->rel)) != NULL) { | 689 | if ((skb = skb_dequeue(&h5->rel)) != NULL) { |