mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-16 12:14:06 +00:00
Bluetooth: ISO: Avoid creating child socket if PA sync is terminating
[ Upstream commit 9f150019f176078144b02c4b9b9dbe7fd5a2fcc3 ] When a PA sync socket is closed, the associated hcon is also unlinked and cleaned up. If there are no other hcons marked with the HCI_CONN_PA_SYNC flag, HCI_OP_LE_PA_TERM_SYNC is sent to controller. Between the time of the command and the moment PA sync is terminated in controller, residual BIGInfo reports might continue to come. This causes a new PA sync hcon to be added, and a new socket to be notified to user space. This commit fixs this by adding a flag on a Broadcast listening socket to mark when the PA sync child has been closed. This flag is checked when BIGInfo reports are indicated in iso_connect_ind, to avoid recreating a hcon and socket if residual reports arrive before PA sync is terminated. Signed-off-by: Iulia Tanasescu <iulia.tanasescu@nxp.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
f2719ecc46
commit
1441054443
1 changed files with 48 additions and 3 deletions
|
@ -52,6 +52,7 @@ static void iso_sock_kill(struct sock *sk);
|
|||
enum {
|
||||
BT_SK_BIG_SYNC,
|
||||
BT_SK_PA_SYNC,
|
||||
BT_SK_PA_SYNC_TERM,
|
||||
};
|
||||
|
||||
struct iso_pinfo {
|
||||
|
@ -80,6 +81,11 @@ static bool iso_match_sid(struct sock *sk, void *data);
|
|||
static bool iso_match_sync_handle(struct sock *sk, void *data);
|
||||
static void iso_sock_disconn(struct sock *sk);
|
||||
|
||||
typedef bool (*iso_sock_match_t)(struct sock *sk, void *data);
|
||||
|
||||
static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst,
|
||||
iso_sock_match_t match, void *data);
|
||||
|
||||
/* ---- ISO timers ---- */
|
||||
#define ISO_CONN_TIMEOUT (HZ * 40)
|
||||
#define ISO_DISCONN_TIMEOUT (HZ * 2)
|
||||
|
@ -188,10 +194,21 @@ static void iso_chan_del(struct sock *sk, int err)
|
|||
sock_set_flag(sk, SOCK_ZAPPED);
|
||||
}
|
||||
|
||||
static bool iso_match_conn_sync_handle(struct sock *sk, void *data)
|
||||
{
|
||||
struct hci_conn *hcon = data;
|
||||
|
||||
if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags))
|
||||
return false;
|
||||
|
||||
return hcon->sync_handle == iso_pi(sk)->sync_handle;
|
||||
}
|
||||
|
||||
static void iso_conn_del(struct hci_conn *hcon, int err)
|
||||
{
|
||||
struct iso_conn *conn = hcon->iso_data;
|
||||
struct sock *sk;
|
||||
struct sock *parent;
|
||||
|
||||
if (!conn)
|
||||
return;
|
||||
|
@ -207,6 +224,25 @@ static void iso_conn_del(struct hci_conn *hcon, int err)
|
|||
|
||||
if (sk) {
|
||||
lock_sock(sk);
|
||||
|
||||
/* While a PA sync hcon is in the process of closing,
|
||||
* mark parent socket with a flag, so that any residual
|
||||
* BIGInfo adv reports that arrive before PA sync is
|
||||
* terminated are not processed anymore.
|
||||
*/
|
||||
if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
|
||||
parent = iso_get_sock_listen(&hcon->src,
|
||||
&hcon->dst,
|
||||
iso_match_conn_sync_handle,
|
||||
hcon);
|
||||
|
||||
if (parent) {
|
||||
set_bit(BT_SK_PA_SYNC_TERM,
|
||||
&iso_pi(parent)->flags);
|
||||
sock_put(parent);
|
||||
}
|
||||
}
|
||||
|
||||
iso_sock_clear_timer(sk);
|
||||
iso_chan_del(sk, err);
|
||||
release_sock(sk);
|
||||
|
@ -543,8 +579,6 @@ static struct sock *__iso_get_sock_listen_by_sid(bdaddr_t *ba, bdaddr_t *bc,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
typedef bool (*iso_sock_match_t)(struct sock *sk, void *data);
|
||||
|
||||
/* Find socket listening:
|
||||
* source bdaddr (Unicast)
|
||||
* destination bdaddr (Broadcast only)
|
||||
|
@ -1756,9 +1790,20 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
|||
/* Try to get PA sync listening socket, if it exists */
|
||||
sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
|
||||
iso_match_pa_sync_flag, NULL);
|
||||
if (!sk)
|
||||
|
||||
if (!sk) {
|
||||
sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
|
||||
iso_match_sync_handle, ev2);
|
||||
|
||||
/* If PA Sync is in process of terminating,
|
||||
* do not handle any more BIGInfo adv reports.
|
||||
*/
|
||||
|
||||
if (sk && test_bit(BT_SK_PA_SYNC_TERM,
|
||||
&iso_pi(sk)->flags))
|
||||
return lm;
|
||||
}
|
||||
|
||||
if (sk) {
|
||||
int err;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue