diff --git a/sound/usb/card.c b/sound/usb/card.c index 524688e4c144..1f6c247f773a 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -673,6 +673,9 @@ static void usb_audio_disconnect(struct usb_interface *intf) card = chip->card; + if (chip->disconnect_cb) + chip->disconnect_cb(chip); + mutex_lock(®ister_mutex); if (atomic_inc_return(&chip->shutdown) == 1) { struct snd_usb_stream *as; @@ -707,8 +710,6 @@ static void usb_audio_disconnect(struct usb_interface *intf) if (chip->num_interfaces <= 0) { usb_chip[chip->index] = NULL; mutex_unlock(®ister_mutex); - if (chip->disconnect_cb) - chip->disconnect_cb(chip); snd_card_free_when_closed(card); } else { mutex_unlock(®ister_mutex); diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c index fa0206cc14c6..8337d11bad12 100644 --- a/sound/usb/usb_audio_qmi_svc.c +++ b/sound/usb/usb_audio_qmi_svc.c @@ -134,6 +134,12 @@ static struct msg_desc uaudio_stream_resp_desc = { .ei_array = qmi_uaudio_stream_resp_msg_v01_ei, }; +static struct msg_desc uaudio_stream_ind_desc = { + .max_msg_len = QMI_UAUDIO_STREAM_IND_MSG_V01_MAX_MSG_LEN, + .msg_id = QMI_UADUIO_STREAM_IND_V01, + .ei_array = qmi_uaudio_stream_ind_msg_v01_ei, +}; + enum mem_type { MEM_EVENT_RING, MEM_DCBA, @@ -643,24 +649,18 @@ void uaudio_disconnect_cb(struct snd_usb_audio *chip) int ret, if_idx; struct uaudio_dev *dev; int card_num = chip->card_num; + struct uaudio_qmi_svc *svc = uaudio_svc; + struct qmi_uaudio_stream_ind_msg_v01 disconnect_ind = {0}; pr_debug("%s: for card# %d\n", __func__, card_num); - mutex_lock(&chip->dev_lock); if (card_num >= SNDRV_CARDS) { pr_err("%s: invalid card number\n", __func__); - goto done; + return; } + mutex_lock(&chip->dev_lock); dev = &uadev[card_num]; - if (atomic_read(&dev->in_use)) { - ret = wait_event_interruptible(dev->disconnect_wq, - !atomic_read(&dev->in_use)); - if (ret < 0) { - pr_debug("%s: failed with ret %d\n", __func__, ret); - goto done; - } - } /* clean up */ if (!dev->udev) { @@ -668,6 +668,30 @@ void uaudio_disconnect_cb(struct snd_usb_audio *chip) goto done; } + if (atomic_read(&dev->in_use)) { + mutex_unlock(&chip->dev_lock); + + pr_debug("%s: sending qmi indication disconnect\n", __func__); + disconnect_ind.dev_event = USB_AUDIO_DEV_DISCONNECT_V01; + disconnect_ind.slot_id = dev->udev->slot_id; + ret = qmi_send_ind(svc->uaudio_svc_hdl, svc->curr_conn, + &uaudio_stream_ind_desc, &disconnect_ind, + sizeof(disconnect_ind)); + if (ret < 0) { + pr_err("%s: qmi send failed wiht err: %d\n", + __func__, ret); + return; + } + + ret = wait_event_interruptible(dev->disconnect_wq, + !atomic_read(&dev->in_use)); + if (ret < 0) { + pr_debug("%s: failed with ret %d\n", __func__, ret); + return; + } + mutex_lock(&chip->dev_lock); + } + /* free xfer buffer and unmap xfer ring and buf per interface */ for (if_idx = 0; if_idx < dev->num_intf; if_idx++) { if (!dev->info[if_idx].in_use)