sound: usb: Send explicit device disconnect to clients
Explicitly send device disconnect notification to client so that client can disable audio streams. This will in turn enable sound usb driver to release usb device and notify device removal to user-space. User-space will clean up audio session. Without this change sound usb driver is blocking usb device release till audio streams are disabled. However, audio streams are only disabled when user-space cleans up audio session on usb device removal which is blocked. This change is trying to fix this deadlock condition by notifying device disconnect to clients explicitly. Change-Id: I7e5a8aca84a7a620bb61eb0ace8a6b6c622f89de Signed-off-by: Vamsi Krishna Samavedam <vskrishn@codeaurora.org>
This commit is contained in:
parent
3dc7ca5e82
commit
b73866cdb1
2 changed files with 37 additions and 12 deletions
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue