Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b73866cd authored by Vamsi Krishna Samavedam's avatar Vamsi Krishna Samavedam
Browse files

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: default avatarVamsi Krishna Samavedam <vskrishn@codeaurora.org>
parent 3dc7ca5e
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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(&register_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(&register_mutex);
		if (chip->disconnect_cb)
			chip->disconnect_cb(chip);
		snd_card_free_when_closed(card);
	} else {
		mutex_unlock(&register_mutex);
+33 −9
Original line number Diff line number Diff line
@@ -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,29 +649,47 @@ 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];

	/* clean up */
	if (!dev->udev) {
		pr_debug("%s: no clean up required\n", __func__);
		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);
			goto done;
		}
			return;
		}

	/* clean up */
	if (!dev->udev) {
		pr_debug("%s: no clean up required\n", __func__);
		goto done;
		mutex_lock(&chip->dev_lock);
	}

	/* free xfer buffer and unmap xfer ring and buf per interface */