mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 05:02:31 +00:00
Bluetooth: ISO: Avoid creating child socket if PA sync is terminating
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>
This commit is contained in:
parent
d03376c185
commit
9f150019f1
@ -54,6 +54,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 {
|
||||
@ -82,6 +83,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)
|
||||
@ -190,10 +196,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;
|
||||
@ -209,6 +226,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);
|
||||
@ -545,8 +581,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)
|
||||
@ -1888,9 +1922,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…
Reference in New Issue
Block a user