aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_request.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2015-11-11 01:30:45 -0500
committerMarcel Holtmann <marcel@holtmann.org>2015-11-19 11:50:31 -0500
commit2154d3f4fb83c812a161c4910948dd876997e111 (patch)
tree0f9151acfc4bcf72165911bcc25713a08faf3a9b /net/bluetooth/hci_request.c
parente68f072b7396574df5324e1cf93e4b0c92460735 (diff)
Bluetooth: Move Stop Discovery to req_workqueue
Since discovery also deals with LE scanning it makes sense to move it behind the same req_workqueue as other LE scanning changes. This also simplifies the logic since we do many of the actions in a synchronous manner. Part of this refactoring is moving hci_req_stop_discovery() to hci_request.c. At the same time the function receives support for properly handling the STOPPING state since that's the state we'll be in when stopping through the req_workqueue. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_request.c')
-rw-r--r--net/bluetooth/hci_request.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index da1e30b85e77..3219ee66faad 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -1221,6 +1221,62 @@ static void start_discovery(struct hci_dev *hdev, u8 *status)
1221 timeout); 1221 timeout);
1222} 1222}
1223 1223
1224bool hci_req_stop_discovery(struct hci_request *req)
1225{
1226 struct hci_dev *hdev = req->hdev;
1227 struct discovery_state *d = &hdev->discovery;
1228 struct hci_cp_remote_name_req_cancel cp;
1229 struct inquiry_entry *e;
1230 bool ret = false;
1231
1232 BT_DBG("%s state %u", hdev->name, hdev->discovery.state);
1233
1234 if (d->state == DISCOVERY_FINDING || d->state == DISCOVERY_STOPPING) {
1235 if (test_bit(HCI_INQUIRY, &hdev->flags))
1236 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1237
1238 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
1239 cancel_delayed_work(&hdev->le_scan_disable);
1240 hci_req_add_le_scan_disable(req);
1241 }
1242
1243 ret = true;
1244 } else {
1245 /* Passive scanning */
1246 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
1247 hci_req_add_le_scan_disable(req);
1248 ret = true;
1249 }
1250 }
1251
1252 /* No further actions needed for LE-only discovery */
1253 if (d->type == DISCOV_TYPE_LE)
1254 return ret;
1255
1256 if (d->state == DISCOVERY_RESOLVING || d->state == DISCOVERY_STOPPING) {
1257 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1258 NAME_PENDING);
1259 if (!e)
1260 return ret;
1261
1262 bacpy(&cp.bdaddr, &e->data.bdaddr);
1263 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1264 &cp);
1265 ret = true;
1266 }
1267
1268 return ret;
1269}
1270
1271static int stop_discovery(struct hci_request *req, unsigned long opt)
1272{
1273 hci_dev_lock(req->hdev);
1274 hci_req_stop_discovery(req);
1275 hci_dev_unlock(req->hdev);
1276
1277 return 0;
1278}
1279
1224static void discov_update(struct work_struct *work) 1280static void discov_update(struct work_struct *work)
1225{ 1281{
1226 struct hci_dev *hdev = container_of(work, struct hci_dev, 1282 struct hci_dev *hdev = container_of(work, struct hci_dev,
@@ -1236,6 +1292,12 @@ static void discov_update(struct work_struct *work)
1236 else 1292 else
1237 hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1293 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
1238 break; 1294 break;
1295 case DISCOVERY_STOPPING:
1296 hci_req_sync(hdev, stop_discovery, 0, HCI_CMD_TIMEOUT, &status);
1297 mgmt_stop_discovery_complete(hdev, status);
1298 if (!status)
1299 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
1300 break;
1239 case DISCOVERY_STOPPED: 1301 case DISCOVERY_STOPPED:
1240 default: 1302 default:
1241 return; 1303 return;