return err;
 }
 
+static bool trigger_discovery(struct hci_request *req, u8 *status)
+{
+       struct hci_dev *hdev = req->hdev;
+       struct hci_cp_le_set_scan_param param_cp;
+       struct hci_cp_le_set_scan_enable enable_cp;
+       struct hci_cp_inquiry inq_cp;
+       /* General inquiry access code (GIAC) */
+       u8 lap[3] = { 0x33, 0x8b, 0x9e };
+       u8 own_addr_type;
+       int err;
+
+       switch (hdev->discovery.type) {
+       case DISCOV_TYPE_BREDR:
+               *status = mgmt_bredr_support(hdev);
+               if (*status)
+                       return false;
+
+               if (test_bit(HCI_INQUIRY, &hdev->flags)) {
+                       *status = MGMT_STATUS_BUSY;
+                       return false;
+               }
+
+               hci_inquiry_cache_flush(hdev);
+
+               memset(&inq_cp, 0, sizeof(inq_cp));
+               memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
+               inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
+               hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
+               break;
+
+       case DISCOV_TYPE_LE:
+       case DISCOV_TYPE_INTERLEAVED:
+               *status = mgmt_le_support(hdev);
+               if (*status)
+                       return false;
+
+               if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
+                   !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
+                       *status = MGMT_STATUS_NOT_SUPPORTED;
+                       return false;
+               }
+
+               if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
+                       /* Don't let discovery abort an outgoing
+                        * connection attempt that's using directed
+                        * advertising.
+                        */
+                       if (hci_conn_hash_lookup_state(hdev, LE_LINK,
+                                                      BT_CONNECT)) {
+                               *status = MGMT_STATUS_REJECTED;
+                               return false;
+                       }
+
+                       disable_advertising(req);
+               }
+
+               /* If controller is scanning, it means the background scanning
+                * is running. Thus, we should temporarily stop it in order to
+                * set the discovery scanning parameters.
+                */
+               if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+                       hci_req_add_le_scan_disable(req);
+
+               memset(¶m_cp, 0, sizeof(param_cp));
+
+               /* All active scans will be done with either a resolvable
+                * private address (when privacy feature has been enabled)
+                * or unresolvable private address.
+                */
+               err = hci_update_random_address(req, true, &own_addr_type);
+               if (err < 0) {
+                       *status = MGMT_STATUS_FAILED;
+                       return false;
+               }
+
+               param_cp.type = LE_SCAN_ACTIVE;
+               param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
+               param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
+               param_cp.own_address_type = own_addr_type;
+               hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+                           ¶m_cp);
+
+               memset(&enable_cp, 0, sizeof(enable_cp));
+               enable_cp.enable = LE_SCAN_ENABLE;
+               enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
+               hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+                           &enable_cp);
+               break;
+
+       default:
+               *status = MGMT_STATUS_INVALID_PARAMS;
+               return false;
+       }
+
+       return true;
+}
+
 static void start_discovery_complete(struct hci_dev *hdev, u8 status)
 {
        struct pending_cmd *cmd;
 {
        struct mgmt_cp_start_discovery *cp = data;
        struct pending_cmd *cmd;
-       struct hci_cp_le_set_scan_param param_cp;
-       struct hci_cp_le_set_scan_enable enable_cp;
-       struct hci_cp_inquiry inq_cp;
        struct hci_request req;
-       /* General inquiry access code (GIAC) */
-       u8 lap[3] = { 0x33, 0x8b, 0x9e };
-       u8 status, own_addr_type;
+       u8 status;
        int err;
 
        BT_DBG("%s", hdev->name);
 
        hci_req_init(&req, hdev);
 
-       switch (hdev->discovery.type) {
-       case DISCOV_TYPE_BREDR:
-               status = mgmt_bredr_support(hdev);
-               if (status) {
-                       err = cmd_complete(sk, hdev->id,
-                                          MGMT_OP_START_DISCOVERY, status,
-                                          &cp->type, sizeof(cp->type));
-                       mgmt_pending_remove(cmd);
-                       goto failed;
-               }
-
-               if (test_bit(HCI_INQUIRY, &hdev->flags)) {
-                       err = cmd_complete(sk, hdev->id,
-                                          MGMT_OP_START_DISCOVERY,
-                                          MGMT_STATUS_BUSY, &cp->type,
-                                          sizeof(cp->type));
-                       mgmt_pending_remove(cmd);
-                       goto failed;
-               }
-
-               hci_inquiry_cache_flush(hdev);
-
-               memset(&inq_cp, 0, sizeof(inq_cp));
-               memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
-               inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
-               hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
-               break;
-
-       case DISCOV_TYPE_LE:
-       case DISCOV_TYPE_INTERLEAVED:
-               status = mgmt_le_support(hdev);
-               if (status) {
-                       err = cmd_complete(sk, hdev->id,
-                                          MGMT_OP_START_DISCOVERY, status,
-                                          &cp->type, sizeof(cp->type));
-                       mgmt_pending_remove(cmd);
-                       goto failed;
-               }
-
-               if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
-                   !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
-                       err = cmd_complete(sk, hdev->id,
-                                          MGMT_OP_START_DISCOVERY,
-                                          MGMT_STATUS_NOT_SUPPORTED,
-                                          &cp->type, sizeof(cp->type));
-                       mgmt_pending_remove(cmd);
-                       goto failed;
-               }
-
-               if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
-                       /* Don't let discovery abort an outgoing
-                        * connection attempt that's using directed
-                        * advertising.
-                        */
-                       if (hci_conn_hash_lookup_state(hdev, LE_LINK,
-                                                      BT_CONNECT)) {
-                               err = cmd_complete(sk, hdev->id,
-                                                  MGMT_OP_START_DISCOVERY,
-                                                  MGMT_STATUS_REJECTED,
-                                                  &cp->type,
-                                                  sizeof(cp->type));
-                               mgmt_pending_remove(cmd);
-                               goto failed;
-                       }
-
-                       disable_advertising(&req);
-               }
-
-               /* If controller is scanning, it means the background scanning
-                * is running. Thus, we should temporarily stop it in order to
-                * set the discovery scanning parameters.
-                */
-               if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
-                       hci_req_add_le_scan_disable(&req);
-
-               memset(¶m_cp, 0, sizeof(param_cp));
-
-               /* All active scans will be done with either a resolvable
-                * private address (when privacy feature has been enabled)
-                * or unresolvable private address.
-                */
-               err = hci_update_random_address(&req, true, &own_addr_type);
-               if (err < 0) {
-                       err = cmd_complete(sk, hdev->id,
-                                          MGMT_OP_START_DISCOVERY,
-                                          MGMT_STATUS_FAILED,
-                                          &cp->type, sizeof(cp->type));
-                       mgmt_pending_remove(cmd);
-                       goto failed;
-               }
-
-               param_cp.type = LE_SCAN_ACTIVE;
-               param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
-               param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
-               param_cp.own_address_type = own_addr_type;
-               hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
-                           ¶m_cp);
-
-               memset(&enable_cp, 0, sizeof(enable_cp));
-               enable_cp.enable = LE_SCAN_ENABLE;
-               enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
-               hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
-                           &enable_cp);
-               break;
-
-       default:
+       if (!trigger_discovery(&req, &status)) {
                err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-                                  MGMT_STATUS_INVALID_PARAMS,
-                                  &cp->type, sizeof(cp->type));
+                                  status, &cp->type, sizeof(cp->type));
                mgmt_pending_remove(cmd);
                goto failed;
        }