瀏覽代碼

Bluetooth: Fix hci_inquiry ioctl usage

Since the HCI request framework was properly fixed, the hci_req_sync
call, in hci_inquiry, will return as soon as the HCI command completes
(not the Inquiry procedure). However, in inquiry ioctl implementation,
we want to sleep the user process until the inquiry procedure finishes.

This patch changes hci_inquiry so, in case the HCI Inquiry command
was executed successfully, it waits the HCI_INQUIRY flag to be cleared.
This way, the user process will sleep until the inquiry procedure
finishes.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Andre Guedes 12 年之前
父節點
當前提交
3e13fa1e1f
共有 2 個文件被更改,包括 18 次插入0 次删除
  1. 13 0
      net/bluetooth/hci_core.c
  2. 5 0
      net/bluetooth/hci_event.c

+ 13 - 0
net/bluetooth/hci_core.c

@@ -818,6 +818,12 @@ static void hci_inq_req(struct hci_request *req, unsigned long opt)
 	hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
 	hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
 }
 }
 
 
+static int wait_inquiry(void *word)
+{
+	schedule();
+	return signal_pending(current);
+}
+
 int hci_inquiry(void __user *arg)
 int hci_inquiry(void __user *arg)
 {
 {
 	__u8 __user *ptr = arg;
 	__u8 __user *ptr = arg;
@@ -849,6 +855,13 @@ int hci_inquiry(void __user *arg)
 				   timeo);
 				   timeo);
 		if (err < 0)
 		if (err < 0)
 			goto done;
 			goto done;
+
+		/* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is
+		 * cleared). If it is interrupted by a signal, return -EINTR.
+		 */
+		if (wait_on_bit(&hdev->flags, HCI_INQUIRY, wait_inquiry,
+				TASK_INTERRUPTIBLE))
+			return -EINTR;
 	}
 	}
 
 
 	/* for unlimited number of responses we will use buffer with
 	/* for unlimited number of responses we will use buffer with

+ 5 - 0
net/bluetooth/hci_event.c

@@ -48,6 +48,8 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 	}
 
 
 	clear_bit(HCI_INQUIRY, &hdev->flags);
 	clear_bit(HCI_INQUIRY, &hdev->flags);
+	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
+	wake_up_bit(&hdev->flags, HCI_INQUIRY);
 
 
 	hci_dev_lock(hdev);
 	hci_dev_lock(hdev);
 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
 	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
@@ -1603,6 +1605,9 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
 	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
 		return;
 		return;
 
 
+	smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
+	wake_up_bit(&hdev->flags, HCI_INQUIRY);
+
 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
 		return;
 		return;