aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c85
1 files changed, 60 insertions, 25 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7384f1161336..06c2e652e4b6 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2199,12 +2199,14 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status)
2199{ 2199{
2200 struct cmd_lookup match = { NULL, hdev }; 2200 struct cmd_lookup match = { NULL, hdev };
2201 2201
2202 hci_dev_lock(hdev);
2203
2202 if (status) { 2204 if (status) {
2203 u8 mgmt_err = mgmt_status(status); 2205 u8 mgmt_err = mgmt_status(status);
2204 2206
2205 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp, 2207 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2206 &mgmt_err); 2208 &mgmt_err);
2207 return; 2209 goto unlock;
2208 } 2210 }
2209 2211
2210 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match); 2212 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
@@ -2222,17 +2224,16 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status)
2222 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { 2224 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2223 struct hci_request req; 2225 struct hci_request req;
2224 2226
2225 hci_dev_lock(hdev);
2226
2227 hci_req_init(&req, hdev); 2227 hci_req_init(&req, hdev);
2228 update_adv_data(&req); 2228 update_adv_data(&req);
2229 update_scan_rsp_data(&req); 2229 update_scan_rsp_data(&req);
2230 hci_req_run(&req, NULL); 2230 hci_req_run(&req, NULL);
2231 2231
2232 hci_update_background_scan(hdev); 2232 hci_update_background_scan(hdev);
2233
2234 hci_dev_unlock(hdev);
2235 } 2233 }
2234
2235unlock:
2236 hci_dev_unlock(hdev);
2236} 2237}
2237 2238
2238static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) 2239static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
@@ -3114,14 +3115,13 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status)
3114 conn->disconn_cfm_cb = NULL; 3115 conn->disconn_cfm_cb = NULL;
3115 3116
3116 hci_conn_drop(conn); 3117 hci_conn_drop(conn);
3117 hci_conn_put(conn);
3118
3119 mgmt_pending_remove(cmd);
3120 3118
3121 /* The device is paired so there is no need to remove 3119 /* The device is paired so there is no need to remove
3122 * its connection parameters anymore. 3120 * its connection parameters anymore.
3123 */ 3121 */
3124 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags); 3122 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
3123
3124 hci_conn_put(conn);
3125} 3125}
3126 3126
3127void mgmt_smp_complete(struct hci_conn *conn, bool complete) 3127void mgmt_smp_complete(struct hci_conn *conn, bool complete)
@@ -3130,8 +3130,10 @@ void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3130 struct pending_cmd *cmd; 3130 struct pending_cmd *cmd;
3131 3131
3132 cmd = find_pairing(conn); 3132 cmd = find_pairing(conn);
3133 if (cmd) 3133 if (cmd) {
3134 cmd->cmd_complete(cmd, status); 3134 cmd->cmd_complete(cmd, status);
3135 mgmt_pending_remove(cmd);
3136 }
3135} 3137}
3136 3138
3137static void pairing_complete_cb(struct hci_conn *conn, u8 status) 3139static void pairing_complete_cb(struct hci_conn *conn, u8 status)
@@ -3141,10 +3143,13 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3141 BT_DBG("status %u", status); 3143 BT_DBG("status %u", status);
3142 3144
3143 cmd = find_pairing(conn); 3145 cmd = find_pairing(conn);
3144 if (!cmd) 3146 if (!cmd) {
3145 BT_DBG("Unable to find a pending command"); 3147 BT_DBG("Unable to find a pending command");
3146 else 3148 return;
3147 cmd->cmd_complete(cmd, mgmt_status(status)); 3149 }
3150
3151 cmd->cmd_complete(cmd, mgmt_status(status));
3152 mgmt_pending_remove(cmd);
3148} 3153}
3149 3154
3150static void le_pairing_complete_cb(struct hci_conn *conn, u8 status) 3155static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
@@ -3157,10 +3162,13 @@ static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
3157 return; 3162 return;
3158 3163
3159 cmd = find_pairing(conn); 3164 cmd = find_pairing(conn);
3160 if (!cmd) 3165 if (!cmd) {
3161 BT_DBG("Unable to find a pending command"); 3166 BT_DBG("Unable to find a pending command");
3162 else 3167 return;
3163 cmd->cmd_complete(cmd, mgmt_status(status)); 3168 }
3169
3170 cmd->cmd_complete(cmd, mgmt_status(status));
3171 mgmt_pending_remove(cmd);
3164} 3172}
3165 3173
3166static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, 3174static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -3274,8 +3282,10 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3274 cmd->user_data = hci_conn_get(conn); 3282 cmd->user_data = hci_conn_get(conn);
3275 3283
3276 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) && 3284 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
3277 hci_conn_security(conn, sec_level, auth_type, true)) 3285 hci_conn_security(conn, sec_level, auth_type, true)) {
3278 pairing_complete(cmd, 0); 3286 cmd->cmd_complete(cmd, 0);
3287 mgmt_pending_remove(cmd);
3288 }
3279 3289
3280 err = 0; 3290 err = 0;
3281 3291
@@ -3317,7 +3327,8 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3317 goto unlock; 3327 goto unlock;
3318 } 3328 }
3319 3329
3320 pairing_complete(cmd, MGMT_STATUS_CANCELLED); 3330 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3331 mgmt_pending_remove(cmd);
3321 3332
3322 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0, 3333 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3323 addr, sizeof(*addr)); 3334 addr, sizeof(*addr));
@@ -3791,7 +3802,7 @@ static bool trigger_discovery(struct hci_request *req, u8 *status)
3791 3802
3792 /* All active scans will be done with either a resolvable 3803 /* All active scans will be done with either a resolvable
3793 * private address (when privacy feature has been enabled) 3804 * private address (when privacy feature has been enabled)
3794 * or unresolvable private address. 3805 * or non-resolvable private address.
3795 */ 3806 */
3796 err = hci_update_random_address(req, true, &own_addr_type); 3807 err = hci_update_random_address(req, true, &own_addr_type);
3797 if (err < 0) { 3808 if (err < 0) {
@@ -4279,12 +4290,14 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4279{ 4290{
4280 struct cmd_lookup match = { NULL, hdev }; 4291 struct cmd_lookup match = { NULL, hdev };
4281 4292
4293 hci_dev_lock(hdev);
4294
4282 if (status) { 4295 if (status) {
4283 u8 mgmt_err = mgmt_status(status); 4296 u8 mgmt_err = mgmt_status(status);
4284 4297
4285 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, 4298 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4286 cmd_status_rsp, &mgmt_err); 4299 cmd_status_rsp, &mgmt_err);
4287 return; 4300 goto unlock;
4288 } 4301 }
4289 4302
4290 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) 4303 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
@@ -4299,6 +4312,9 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4299 4312
4300 if (match.sk) 4313 if (match.sk)
4301 sock_put(match.sk); 4314 sock_put(match.sk);
4315
4316unlock:
4317 hci_dev_unlock(hdev);
4302} 4318}
4303 4319
4304static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, 4320static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -6081,6 +6097,11 @@ static int powered_update_hci(struct hci_dev *hdev)
6081 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp); 6097 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
6082 } 6098 }
6083 6099
6100 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6101 u8 sc = 0x01;
6102 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, sizeof(sc), &sc);
6103 }
6104
6084 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && 6105 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6085 lmp_bredr_capable(hdev)) { 6106 lmp_bredr_capable(hdev)) {
6086 struct hci_cp_write_le_host_supported cp; 6107 struct hci_cp_write_le_host_supported cp;
@@ -6130,8 +6151,7 @@ static int powered_update_hci(struct hci_dev *hdev)
6130int mgmt_powered(struct hci_dev *hdev, u8 powered) 6151int mgmt_powered(struct hci_dev *hdev, u8 powered)
6131{ 6152{
6132 struct cmd_lookup match = { NULL, hdev }; 6153 struct cmd_lookup match = { NULL, hdev };
6133 u8 status_not_powered = MGMT_STATUS_NOT_POWERED; 6154 u8 status, zero_cod[] = { 0, 0, 0 };
6134 u8 zero_cod[] = { 0, 0, 0 };
6135 int err; 6155 int err;
6136 6156
6137 if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 6157 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
@@ -6147,7 +6167,20 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
6147 } 6167 }
6148 6168
6149 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); 6169 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6150 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status_not_powered); 6170
6171 /* If the power off is because of hdev unregistration let
6172 * use the appropriate INVALID_INDEX status. Otherwise use
6173 * NOT_POWERED. We cover both scenarios here since later in
6174 * mgmt_index_removed() any hci_conn callbacks will have already
6175 * been triggered, potentially causing misleading DISCONNECTED
6176 * status responses.
6177 */
6178 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6179 status = MGMT_STATUS_INVALID_INDEX;
6180 else
6181 status = MGMT_STATUS_NOT_POWERED;
6182
6183 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
6151 6184
6152 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) 6185 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6153 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, 6186 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
@@ -6681,8 +6714,10 @@ void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
6681 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev), 6714 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6682 cmd ? cmd->sk : NULL); 6715 cmd ? cmd->sk : NULL);
6683 6716
6684 if (cmd) 6717 if (cmd) {
6685 pairing_complete(cmd, status); 6718 cmd->cmd_complete(cmd, status);
6719 mgmt_pending_remove(cmd);
6720 }
6686} 6721}
6687 6722
6688void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) 6723void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)