struct hci_ev_le_pa_sync_established *ev = data;
        int mask = hdev->link_mode;
        __u8 flags = 0;
+       struct hci_conn *bis;
 
        bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
-       if (ev->status)
-               return;
-
        hci_dev_lock(hdev);
 
        hci_dev_clear_flag(hdev, HCI_PA_SYNC);
 
        mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ISO_LINK, &flags);
-       if (!(mask & HCI_LM_ACCEPT))
+       if (!(mask & HCI_LM_ACCEPT)) {
                hci_le_pa_term_sync(hdev, ev->handle);
+               goto unlock;
+       }
+
+       if (!(flags & HCI_PROTO_DEFER))
+               goto unlock;
+
+       /* Add connection to indicate the PA sync event */
+       bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
+                          HCI_ROLE_SLAVE);
 
+       if (!bis)
+               goto unlock;
+
+       if (ev->status)
+               set_bit(HCI_CONN_PA_SYNC_FAILED, &bis->flags);
+       else
+               set_bit(HCI_CONN_PA_SYNC, &bis->flags);
+
+       /* Notify connection to iso layer */
+       hci_connect_cfm(bis, ev->status);
+
+unlock:
        hci_dev_unlock(hdev);
 }
 
 {
        struct hci_evt_le_big_sync_estabilished *ev = data;
        struct hci_conn *bis;
+       struct hci_conn *pa_sync;
        int i;
 
        bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
        hci_dev_lock(hdev);
 
+       if (!ev->status) {
+               pa_sync = hci_conn_hash_lookup_pa_sync(hdev, ev->handle);
+               if (pa_sync)
+                       /* Also mark the BIG sync established event on the
+                        * associated PA sync hcon
+                        */
+                       set_bit(HCI_CONN_BIG_SYNC, &pa_sync->flags);
+       }
+
        for (i = 0; i < ev->num_bis; i++) {
                u16 handle = le16_to_cpu(ev->bis[i]);
                __le32 interval;
                        bis->handle = handle;
                }
 
+               if (ev->status != 0x42)
+                       /* Mark PA sync as established */
+                       set_bit(HCI_CONN_PA_SYNC, &bis->flags);
+
                bis->iso_qos.bcast.big = ev->handle;
                memset(&interval, 0, sizeof(interval));
                memcpy(&interval, ev->latency, sizeof(ev->latency));
 
 /* iso_pinfo flags values */
 enum {
        BT_SK_BIG_SYNC,
+       BT_SK_PA_SYNC,
 };
 
 struct iso_pinfo {
 
 static bool check_ucast_qos(struct bt_iso_qos *qos);
 static bool check_bcast_qos(struct bt_iso_qos *qos);
+static bool iso_match_sid(struct sock *sk, void *data);
+static void iso_sock_disconn(struct sock *sk);
 
 /* ---- ISO timers ---- */
 #define ISO_CONN_TIMEOUT       (HZ * 40)
                iso_sock_kill(sk);
        }
 
+       /* If listening socket stands for a PA sync connection,
+        * properly disconnect the hcon and socket.
+        */
+       if (iso_pi(parent)->conn && iso_pi(parent)->conn->hcon &&
+           test_bit(HCI_CONN_PA_SYNC, &iso_pi(parent)->conn->hcon->flags)) {
+               iso_sock_disconn(parent);
+               return;
+       }
+
        parent->sk_state  = BT_CLOSED;
        sock_set_flag(parent, SOCK_ZAPPED);
 }
        sock_put(sk);
 }
 
+static void iso_sock_disconn(struct sock *sk)
+{
+       sk->sk_state = BT_DISCONN;
+       iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT);
+       iso_conn_lock(iso_pi(sk)->conn);
+       hci_conn_drop(iso_pi(sk)->conn->hcon);
+       iso_pi(sk)->conn->hcon = NULL;
+       iso_conn_unlock(iso_pi(sk)->conn);
+}
+
 static void __iso_sock_close(struct sock *sk)
 {
        BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
        case BT_CONNECT:
        case BT_CONNECTED:
        case BT_CONFIG:
-               if (iso_pi(sk)->conn->hcon) {
-                       sk->sk_state = BT_DISCONN;
-                       iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT);
-                       iso_conn_lock(iso_pi(sk)->conn);
-                       hci_conn_drop(iso_pi(sk)->conn->hcon);
-                       iso_pi(sk)->conn->hcon = NULL;
-                       iso_conn_unlock(iso_pi(sk)->conn);
-               } else {
+               if (iso_pi(sk)->conn->hcon)
+                       iso_sock_disconn(sk);
+               else
                        iso_chan_del(sk, ECONNRESET);
-               }
                break;
 
        case BT_CONNECT2:
-               iso_chan_del(sk, ECONNRESET);
+               if (iso_pi(sk)->conn->hcon &&
+                   (test_bit(HCI_CONN_PA_SYNC, &iso_pi(sk)->conn->hcon->flags) ||
+                   test_bit(HCI_CONN_PA_SYNC_FAILED, &iso_pi(sk)->conn->hcon->flags)))
+                       iso_sock_disconn(sk);
+               else
+                       iso_chan_del(sk, ECONNRESET);
                break;
        case BT_DISCONN:
                iso_chan_del(sk, ECONNRESET);
        hci_send_cmd(hdev, HCI_OP_LE_ACCEPT_CIS, sizeof(cp), &cp);
 }
 
+static void iso_conn_big_sync(struct sock *sk)
+{
+       int err;
+       struct hci_dev *hdev;
+
+       hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
+                            iso_pi(sk)->src_type);
+
+       if (!hdev)
+               return;
+
+       if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
+               err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
+                                            &iso_pi(sk)->qos,
+                                            iso_pi(sk)->sync_handle,
+                                            iso_pi(sk)->bc_num_bis,
+                                            iso_pi(sk)->bc_bis);
+               if (err)
+                       bt_dev_err(hdev, "hci_le_big_create_sync: %d",
+                                  err);
+       }
+}
+
 static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
                            size_t len, int flags)
 {
                lock_sock(sk);
                switch (sk->sk_state) {
                case BT_CONNECT2:
-                       iso_conn_defer_accept(pi->conn->hcon);
-                       sk->sk_state = BT_CONFIG;
+                       if (pi->conn->hcon &&
+                           test_bit(HCI_CONN_PA_SYNC, &pi->conn->hcon->flags)) {
+                               iso_conn_big_sync(sk);
+                               sk->sk_state = BT_LISTEN;
+                               set_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags);
+                       } else {
+                               iso_conn_defer_accept(pi->conn->hcon);
+                               sk->sk_state = BT_CONFIG;
+                       }
                        release_sock(sk);
                        return 0;
                case BT_CONNECT:
        return ev->handle == iso_pi(sk)->qos.bcast.big;
 }
 
+static bool iso_match_pa_sync_flag(struct sock *sk, void *data)
+{
+       return test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags);
+}
+
 static void iso_conn_ready(struct iso_conn *conn)
 {
-       struct sock *parent;
+       struct sock *parent = NULL;
        struct sock *sk = conn->sk;
-       struct hci_ev_le_big_sync_estabilished *ev;
+       struct hci_ev_le_big_sync_estabilished *ev = NULL;
+       struct hci_ev_le_pa_sync_established *ev2 = NULL;
        struct hci_conn *hcon;
 
        BT_DBG("conn %p", conn);
                if (!hcon)
                        return;
 
-               ev = hci_recv_event_data(hcon->hdev,
-                                        HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
-               if (ev)
+               if (test_bit(HCI_CONN_BIG_SYNC, &hcon->flags) ||
+                   test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
+                       ev = hci_recv_event_data(hcon->hdev,
+                                                HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
+
+                       /* Get reference to PA sync parent socket, if it exists */
                        parent = iso_get_sock_listen(&hcon->src,
                                                     &hcon->dst,
-                                                    iso_match_big, ev);
-               else
+                                                    iso_match_pa_sync_flag, NULL);
+                       if (!parent && ev)
+                               parent = iso_get_sock_listen(&hcon->src,
+                                                            &hcon->dst,
+                                                            iso_match_big, ev);
+               } else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags) ||
+                               test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
+                       ev2 = hci_recv_event_data(hcon->hdev,
+                                                 HCI_EV_LE_PA_SYNC_ESTABLISHED);
+                       if (ev2)
+                               parent = iso_get_sock_listen(&hcon->src,
+                                                            &hcon->dst,
+                                                            iso_match_sid, ev2);
+               }
+
+               if (!parent)
                        parent = iso_get_sock_listen(&hcon->src,
-                                                    BDADDR_ANY, NULL, NULL);
+                                                       BDADDR_ANY, NULL, NULL);
 
                if (!parent)
                        return;
                iso_sock_init(sk, parent);
 
                bacpy(&iso_pi(sk)->src, &hcon->src);
-               iso_pi(sk)->src_type = hcon->src_type;
+
+               /* Convert from HCI to three-value type */
+               if (hcon->src_type == ADDR_LE_DEV_PUBLIC)
+                       iso_pi(sk)->src_type = BDADDR_LE_PUBLIC;
+               else
+                       iso_pi(sk)->src_type = BDADDR_LE_RANDOM;
 
                /* If hcon has no destination address (BDADDR_ANY) it means it
-                * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED so we need to
-                * initialize using the parent socket destination address.
+                * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED or
+                * HCI_EV_LE_PA_SYNC_ESTABLISHED so we need to initialize using
+                * the parent socket destination address.
                 */
                if (!bacmp(&hcon->dst, BDADDR_ANY)) {
                        bacpy(&hcon->dst, &iso_pi(parent)->dst);
                        hcon->sync_handle = iso_pi(parent)->sync_handle;
                }
 
+               if (ev2 && !ev2->status) {
+                       iso_pi(sk)->sync_handle = iso_pi(parent)->sync_handle;
+                       iso_pi(sk)->qos = iso_pi(parent)->qos;
+                       iso_pi(sk)->bc_num_bis = iso_pi(parent)->bc_num_bis;
+                       memcpy(iso_pi(sk)->bc_bis, iso_pi(parent)->bc_bis, ISO_MAX_NUM_BIS);
+               }
+
                bacpy(&iso_pi(sk)->dst, &hcon->dst);
                iso_pi(sk)->dst_type = hcon->dst_type;
 
                hci_conn_hold(hcon);
                iso_chan_add(conn, sk, parent);
 
-               if (ev && ((struct hci_evt_le_big_sync_estabilished *)ev)->status) {
+               if ((ev && ((struct hci_evt_le_big_sync_estabilished *)ev)->status) ||
+                   (ev2 && ev2->status)) {
                        /* Trigger error signal on child socket */
                        sk->sk_err = ECONNREFUSED;
                        sk->sk_error_report(sk);
        if (ev1) {
                sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, iso_match_sid,
                                         ev1);
-               if (sk)
+               if (sk && !ev1->status)
                        iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle);
 
                goto done;
 
        ev2 = hci_recv_event_data(hdev, HCI_EVT_LE_BIG_INFO_ADV_REPORT);
        if (ev2) {
+               /* Try to get PA sync listening socket, if it exists */
                sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
-                                        iso_match_sync_handle, ev2);
+                                               iso_match_pa_sync_flag, NULL);
+               if (!sk)
+                       sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
+                                                iso_match_sync_handle, ev2);
                if (sk) {
                        int err;
 
                        if (ev2->num_bis < iso_pi(sk)->bc_num_bis)
                                iso_pi(sk)->bc_num_bis = ev2->num_bis;
 
-                       if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
-                               err = hci_le_big_create_sync(hdev,
+                       if (!test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) &&
+                           !test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
+                               err = hci_le_big_create_sync(hdev, NULL,
                                                             &iso_pi(sk)->qos,
                                                             iso_pi(sk)->sync_handle,
                                                             iso_pi(sk)->bc_num_bis,
 
        BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
 
-       /* Similar to the success case, if HCI_CONN_BIG_SYNC_FAILED is set,
-        * queue the failed bis connection into the accept queue of the
-        * listening socket and wake up userspace, to inform the user about
-        * the BIG sync failed event.
+       /* Similar to the success case, if HCI_CONN_BIG_SYNC_FAILED or
+        * HCI_CONN_PA_SYNC_FAILED is set, queue the failed connection
+        * into the accept queue of the listening socket and wake up
+        * userspace, to inform the user about the event.
         */
-       if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
+       if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags) ||
+           test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
                struct iso_conn *conn;
 
                conn = iso_conn_add(hcon);