Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 744cf19e authored by Johan Hedberg's avatar Johan Hedberg Committed by Gustavo Padovan
Browse files

Bluetooth: Pass full hci_dev struct to mgmt callbacks



The current global pending command list in mgmt.c is racy. Possibly the
simplest way to fix it is to have per-hci dev lists instead of a global
one (all commands that need a pending struct are hci_dev specific).
This way the list can be protected using the already existing per-hci
dev lock. To enable this refactoring the first thing that needs to be
done is to ensure that the mgmt functions have access to the hci_dev
struct (instead of just the dev id).

Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent 4c659c39
Loading
Loading
Loading
Loading
+33 −28
Original line number Diff line number Diff line
@@ -905,36 +905,41 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,

/* Management interface */
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
int mgmt_index_added(u16 index);
int mgmt_index_removed(u16 index);
int mgmt_powered(u16 index, u8 powered);
int mgmt_discoverable(u16 index, u8 discoverable);
int mgmt_connectable(u16 index, u8 connectable);
int mgmt_write_scan_failed(u16 index, u8 scan, u8 status);
int mgmt_new_link_key(u16 index, struct link_key *key, u8 persistent);
int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 type);
int mgmt_disconnected(u16 index, bdaddr_t *bdaddr, u8 type);
int mgmt_disconnect_failed(u16 index);
int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 type, u8 status);
int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure);
int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value,
							u8 confirm_hint);
int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr,
int mgmt_index_added(struct hci_dev *hdev);
int mgmt_index_removed(struct hci_dev *hdev);
int mgmt_powered(struct hci_dev *hdev, u8 powered);
int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
								u8 persistent);
int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_disconnect_failed(struct hci_dev *hdev);
int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type,
								u8 status);
int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure);
int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
								u8 status);
int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 *dev_class,
							s8 rssi, u8 *eir);
int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
int mgmt_inquiry_failed(u16 index, u8 status);
int mgmt_discovering(u16 index, u8 discovering);
int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr);
int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr);
int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
								u8 status);
int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
						__le32 value, u8 confirm_hint);
int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
								u8 status);
int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
						bdaddr_t *bdaddr, u8 status);
int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status);
int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
						u8 *randomizer, u8 status);
int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type,
					u8 *dev_class, s8 rssi, u8 *eir);
int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name);
int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status);
int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr);

/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
+8 −8
Original line number Diff line number Diff line
@@ -550,7 +550,7 @@ int hci_dev_open(__u16 dev)
		set_bit(HCI_UP, &hdev->flags);
		hci_notify(hdev, HCI_DEV_UP);
		if (!test_bit(HCI_SETUP, &hdev->flags))
			mgmt_powered(hdev->id, 1);
			mgmt_powered(hdev, 1);
	} else {
		/* Init failed, cleanup */
		tasklet_kill(&hdev->rx_task);
@@ -642,7 +642,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
	 * and no tasks are scheduled. */
	hdev->close(hdev);

	mgmt_powered(hdev->id, 0);
	mgmt_powered(hdev, 0);

	/* Clear flags */
	hdev->flags = 0;
@@ -947,7 +947,7 @@ static void hci_power_on(struct work_struct *work)
					msecs_to_jiffies(AUTO_OFF_TIMEOUT));

	if (test_and_clear_bit(HCI_SETUP, &hdev->flags))
		mgmt_index_added(hdev->id);
		mgmt_index_added(hdev);
}

static void hci_power_off(struct work_struct *work)
@@ -1140,7 +1140,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,

	persistent = hci_persistent_key(hdev, conn, type, old_key_type);

	mgmt_new_link_key(hdev->id, key, persistent);
	mgmt_new_link_key(hdev, key, persistent);

	if (!persistent) {
		list_del(&key->list);
@@ -1183,7 +1183,7 @@ int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
	memcpy(id->rand, rand, sizeof(id->rand));

	if (new_key)
		mgmt_new_link_key(hdev->id, key, old_key_type);
		mgmt_new_link_key(hdev, key, old_key_type);

	return 0;
}
@@ -1324,7 +1324,7 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)

	list_add(&entry->list, &hdev->blacklist);

	return mgmt_device_blocked(hdev->id, bdaddr);
	return mgmt_device_blocked(hdev, bdaddr);
}

int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
@@ -1343,7 +1343,7 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
	list_del(&entry->list);
	kfree(entry);

	return mgmt_device_unblocked(hdev->id, bdaddr);
	return mgmt_device_unblocked(hdev, bdaddr);
}

static void hci_clear_adv_cache(unsigned long arg)
@@ -1560,7 +1560,7 @@ void hci_unregister_dev(struct hci_dev *hdev)

	if (!test_bit(HCI_INIT, &hdev->flags) &&
					!test_bit(HCI_SETUP, &hdev->flags))
		mgmt_index_removed(hdev->id);
		mgmt_index_removed(hdev);

	hci_notify(hdev, HCI_DEV_UNREG);

+31 −32
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)

	clear_bit(HCI_INQUIRY, &hdev->flags);

	mgmt_discovering(hdev->id, 0);
	mgmt_discovering(hdev, 0);

	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);

@@ -202,7 +202,7 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
		return;

	if (test_bit(HCI_MGMT, &hdev->flags))
		mgmt_set_local_name_complete(hdev->id, sent, status);
		mgmt_set_local_name_complete(hdev, sent, status);

	if (status)
		return;
@@ -283,7 +283,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
	param = *((__u8 *) sent);

	if (status != 0) {
		mgmt_write_scan_failed(hdev->id, param, status);
		mgmt_write_scan_failed(hdev, param, status);
		hdev->discov_timeout = 0;
		goto done;
	}
@@ -294,21 +294,21 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
	if (param & SCAN_INQUIRY) {
		set_bit(HCI_ISCAN, &hdev->flags);
		if (!old_iscan)
			mgmt_discoverable(hdev->id, 1);
			mgmt_discoverable(hdev, 1);
		if (hdev->discov_timeout > 0) {
			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
			queue_delayed_work(hdev->workqueue, &hdev->discov_off,
									to);
		}
	} else if (old_iscan)
		mgmt_discoverable(hdev->id, 0);
		mgmt_discoverable(hdev, 0);

	if (param & SCAN_PAGE) {
		set_bit(HCI_PSCAN, &hdev->flags);
		if (!old_pscan)
			mgmt_connectable(hdev->id, 1);
			mgmt_connectable(hdev, 1);
	} else if (old_pscan)
		mgmt_connectable(hdev->id, 0);
		mgmt_connectable(hdev, 0);

done:
	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
@@ -835,7 +835,7 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
	BT_DBG("%s status 0x%x", hdev->name, rp->status);

	if (test_bit(HCI_MGMT, &hdev->flags))
		mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
		mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);

	if (rp->status != 0)
		return;
@@ -856,7 +856,7 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
	BT_DBG("%s status 0x%x", hdev->name, rp->status);

	if (test_bit(HCI_MGMT, &hdev->flags))
		mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
		mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
								rp->status);
}
static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
@@ -886,7 +886,7 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
	BT_DBG("%s status 0x%x", hdev->name, rp->status);

	if (test_bit(HCI_MGMT, &hdev->flags))
		mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr,
		mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
								rp->status);
}

@@ -898,7 +898,7 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
	BT_DBG("%s status 0x%x", hdev->name, rp->status);

	if (test_bit(HCI_MGMT, &hdev->flags))
		mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr,
		mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
								rp->status);
}

@@ -909,7 +909,7 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,

	BT_DBG("%s status 0x%x", hdev->name, rp->status);

	mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash,
	mgmt_read_local_oob_data_reply_complete(hdev, rp->hash,
						rp->randomizer, rp->status);
}

@@ -986,13 +986,13 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
		hci_conn_check_pending(hdev);
		if (test_bit(HCI_MGMT, &hdev->flags))
			mgmt_inquiry_failed(hdev->id, status);
			mgmt_inquiry_failed(hdev, status);
		return;
	}

	set_bit(HCI_INQUIRY, &hdev->flags);

	mgmt_discovering(hdev->id, 1);
	mgmt_discovering(hdev, 1);
}

static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
@@ -1378,7 +1378,7 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
	if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
		return;

	mgmt_discovering(hdev->id, 0);
	mgmt_discovering(hdev, 0);
}

static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1404,7 +1404,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
		data.rssi		= 0x00;
		data.ssp_mode		= 0x00;
		hci_inquiry_cache_update(hdev, &data);
		mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK,
		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK,
						info->dev_class, 0, NULL);
	}

@@ -1439,7 +1439,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
			conn->state = BT_CONFIG;
			hci_conn_hold(conn);
			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
			mgmt_connected(hdev->id, &ev->bdaddr, conn->type);
			mgmt_connected(hdev, &ev->bdaddr, conn->type);
		} else
			conn->state = BT_CONNECTED;

@@ -1471,7 +1471,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
	} else {
		conn->state = BT_CLOSED;
		if (conn->type == ACL_LINK)
			mgmt_connect_failed(hdev->id, &ev->bdaddr, conn->type,
			mgmt_connect_failed(hdev, &ev->bdaddr, conn->type,
								ev->status);
	}

@@ -1572,7 +1572,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
	BT_DBG("%s status %d", hdev->name, ev->status);

	if (ev->status) {
		mgmt_disconnect_failed(hdev->id);
		mgmt_disconnect_failed(hdev);
		return;
	}

@@ -1585,7 +1585,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
	conn->state = BT_CLOSED;

	if (conn->type == ACL_LINK || conn->type == LE_LINK)
		mgmt_disconnected(hdev->id, &conn->dst, conn->type);
		mgmt_disconnected(hdev, &conn->dst, conn->type);

	hci_proto_disconn_cfm(conn, ev->reason);
	hci_conn_del(conn);
@@ -1616,7 +1616,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
			conn->sec_level = conn->pending_sec_level;
		}
	} else {
		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
		mgmt_auth_failed(hdev, &conn->dst, ev->status);
	}

	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
@@ -1671,7 +1671,7 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
	hci_dev_lock(hdev);

	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
		mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
		mgmt_remote_name(hdev, &ev->bdaddr, ev->name);

	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
	if (!conn)
@@ -2061,7 +2061,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)

	case HCI_OP_DISCONNECT:
		if (ev->status != 0)
			mgmt_disconnect_failed(hdev->id);
			mgmt_disconnect_failed(hdev);
		break;

	case HCI_OP_LE_CREATE_CONN:
@@ -2226,7 +2226,7 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
		else
			secure = 0;

		mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure);
		mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
	}

unlock:
@@ -2409,7 +2409,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
			data.rssi		= info->rssi;
			data.ssp_mode		= 0x00;
			hci_inquiry_cache_update(hdev, &data);
			mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK,
			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK,
						info->dev_class, info->rssi,
						NULL);
		}
@@ -2426,7 +2426,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
			data.rssi		= info->rssi;
			data.ssp_mode		= 0x00;
			hci_inquiry_cache_update(hdev, &data);
			mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK,
			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK,
						info->dev_class, info->rssi,
						NULL);
		}
@@ -2569,7 +2569,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
		data.rssi		= info->rssi;
		data.ssp_mode		= 0x01;
		hci_inquiry_cache_update(hdev, &data);
		mgmt_device_found(hdev->id, &info->bdaddr, ACL_LINK,
		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK,
				info->dev_class, info->rssi, info->data);
	}

@@ -2726,7 +2726,7 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
	}

confirm:
	mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey,
	mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
								confirm_hint);

unlock:
@@ -2752,7 +2752,7 @@ static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_
	 * event gets always produced as initiator and is also mapped to
	 * the mgmt_auth_failed event */
	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
		mgmt_auth_failed(hdev, &conn->dst, ev->status);

	hci_conn_put(conn);

@@ -2833,15 +2833,14 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
	}

	if (ev->status) {
		mgmt_connect_failed(hdev->id, &ev->bdaddr, conn->type,
								ev->status);
		mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, ev->status);
		hci_proto_connect_cfm(conn, ev->status);
		conn->state = BT_CLOSED;
		hci_conn_del(conn);
		goto unlock;
	}

	mgmt_connected(hdev->id, &ev->bdaddr, conn->type);
	mgmt_connected(hdev, &ev->bdaddr, conn->type);

	conn->sec_level = BT_SECURITY_LOW;
	conn->handle = __le16_to_cpu(ev->handle);
+106 −100

File changed.

Preview size limit exceeded, changes collapsed.