aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2013-03-05 13:37:48 -0500
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-03-08 08:40:26 -0500
commit9238f36a5a5097018b90baa42c473d2f916a46f5 (patch)
tree304714fec2ecc9cacea615da399e8f09453f17e8 /net/bluetooth
parent11714b3d7acee54eecf85d41c938923a02fdd054 (diff)
Bluetooth: Add request cmd_complete and cmd_status functions
This patch introduces functions to process the HCI request state when receiving HCI Command Status or Command Complete events. Some HCI commands, like Inquiry do not result in a Command complete event so special handling is needed for them. Inquiry is a particularly important one since it is the only forseeable "non-cmd_complete" command that will make good use of the request functionality, and its completion is either indicated by an Inquiry Complete event of a successful Command Complete for HCI_Inquiry_Cancel. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_core.c85
-rw-r--r--net/bluetooth/hci_event.c7
2 files changed, 92 insertions, 0 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 4f8142bdf655..0ada2ec36e7b 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3208,6 +3208,91 @@ static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
3208 kfree_skb(skb); 3208 kfree_skb(skb);
3209} 3209}
3210 3210
3211static bool hci_req_is_complete(struct hci_dev *hdev)
3212{
3213 struct sk_buff *skb;
3214
3215 skb = skb_peek(&hdev->cmd_q);
3216 if (!skb)
3217 return true;
3218
3219 return bt_cb(skb)->req.start;
3220}
3221
3222void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status)
3223{
3224 hci_req_complete_t req_complete = NULL;
3225 struct sk_buff *skb;
3226 unsigned long flags;
3227
3228 BT_DBG("opcode 0x%04x status 0x%02x", opcode, status);
3229
3230 /* Check that the completed command really matches the last one
3231 * that was sent.
3232 */
3233 if (!hci_sent_cmd_data(hdev, opcode))
3234 return;
3235
3236 /* If the command succeeded and there's still more commands in
3237 * this request the request is not yet complete.
3238 */
3239 if (!status && !hci_req_is_complete(hdev))
3240 return;
3241
3242 /* If this was the last command in a request the complete
3243 * callback would be found in hdev->sent_cmd instead of the
3244 * command queue (hdev->cmd_q).
3245 */
3246 if (hdev->sent_cmd) {
3247 req_complete = bt_cb(hdev->sent_cmd)->req.complete;
3248 if (req_complete)
3249 goto call_complete;
3250 }
3251
3252 /* Remove all pending commands belonging to this request */
3253 spin_lock_irqsave(&hdev->cmd_q.lock, flags);
3254 while ((skb = __skb_dequeue(&hdev->cmd_q))) {
3255 if (bt_cb(skb)->req.start) {
3256 __skb_queue_head(&hdev->cmd_q, skb);
3257 break;
3258 }
3259
3260 req_complete = bt_cb(skb)->req.complete;
3261 kfree_skb(skb);
3262 }
3263 spin_unlock_irqrestore(&hdev->cmd_q.lock, flags);
3264
3265call_complete:
3266 if (req_complete)
3267 req_complete(hdev, status);
3268}
3269
3270void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status)
3271{
3272 hci_req_complete_t req_complete = NULL;
3273
3274 BT_DBG("opcode 0x%04x status 0x%02x", opcode, status);
3275
3276 if (status) {
3277 hci_req_cmd_complete(hdev, opcode, status);
3278 return;
3279 }
3280
3281 /* No need to handle success status if there are more commands */
3282 if (!hci_req_is_complete(hdev))
3283 return;
3284
3285 if (hdev->sent_cmd)
3286 req_complete = bt_cb(hdev->sent_cmd)->req.complete;
3287
3288 /* If the request doesn't have a complete callback or there
3289 * are other commands/requests in the hdev queue we consider
3290 * this request as completed.
3291 */
3292 if (!req_complete || !skb_queue_empty(&hdev->cmd_q))
3293 hci_req_cmd_complete(hdev, opcode, status);
3294}
3295
3211static void hci_rx_work(struct work_struct *work) 3296static void hci_rx_work(struct work_struct *work)
3212{ 3297{
3213 struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work); 3298 struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 14e872aa0d2c..8b878a3bdf69 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -53,6 +53,7 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
53 hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 53 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
54 hci_dev_unlock(hdev); 54 hci_dev_unlock(hdev);
55 55
56 hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
56 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 57 hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
57 58
58 hci_conn_check_pending(hdev); 59 hci_conn_check_pending(hdev);
@@ -1692,6 +1693,7 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1692 1693
1693 BT_DBG("%s status 0x%2.2x", hdev->name, status); 1694 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1694 1695
1696 hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
1695 hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1697 hci_req_complete(hdev, HCI_OP_INQUIRY, status);
1696 1698
1697 hci_conn_check_pending(hdev); 1699 hci_conn_check_pending(hdev);
@@ -2254,6 +2256,7 @@ static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
2254static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2256static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2255{ 2257{
2256 struct hci_ev_cmd_complete *ev = (void *) skb->data; 2258 struct hci_ev_cmd_complete *ev = (void *) skb->data;
2259 u8 status = skb->data[sizeof(*ev)];
2257 __u16 opcode; 2260 __u16 opcode;
2258 2261
2259 skb_pull(skb, sizeof(*ev)); 2262 skb_pull(skb, sizeof(*ev));
@@ -2497,6 +2500,8 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2497 if (ev->opcode != HCI_OP_NOP) 2500 if (ev->opcode != HCI_OP_NOP)
2498 del_timer(&hdev->cmd_timer); 2501 del_timer(&hdev->cmd_timer);
2499 2502
2503 hci_req_cmd_complete(hdev, ev->opcode, status);
2504
2500 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2505 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2501 atomic_set(&hdev->cmd_cnt, 1); 2506 atomic_set(&hdev->cmd_cnt, 1);
2502 if (!skb_queue_empty(&hdev->cmd_q)) 2507 if (!skb_queue_empty(&hdev->cmd_q))
@@ -2590,6 +2595,8 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2590 if (ev->opcode != HCI_OP_NOP) 2595 if (ev->opcode != HCI_OP_NOP)
2591 del_timer(&hdev->cmd_timer); 2596 del_timer(&hdev->cmd_timer);
2592 2597
2598 hci_req_cmd_status(hdev, ev->opcode, ev->status);
2599
2593 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2600 if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
2594 atomic_set(&hdev->cmd_cnt, 1); 2601 atomic_set(&hdev->cmd_cnt, 1);
2595 if (!skb_queue_empty(&hdev->cmd_q)) 2602 if (!skb_queue_empty(&hdev->cmd_q))