sound: usb: Stop endpoints upon disable audio stream request

Currently driver is issuing stop endpoint command after issuing
SET_ALT 0. As part of SET_ALT 0 endpoint drop context flag is set
before issuing configure endpoint command. As per XHCI spec endpoint
should be in stopped state before setting drop context flag otherwise
configure endpoint command may result into undefined behavior. Fix this
by issuing stop endpoint command before SET_ALT 0.

Change-Id: If9ef60db2b0f1af4d6e5e0722414ce738d6580ad
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c
index 1c5b36d..ce1f0ad 100644
--- a/sound/usb/usb_audio_qmi_svc.c
+++ b/sound/usb/usb_audio_qmi_svc.c
@@ -762,25 +762,6 @@
 	struct intf_info *info)
 {
 
-	struct usb_host_endpoint *ep;
-
-	if (info->data_ep_pipe) {
-		ep = usb_pipe_endpoint(udev, info->data_ep_pipe);
-		if (!ep)
-			pr_debug("%s: no data ep\n", __func__);
-		else
-			usb_stop_endpoint(udev, ep);
-		info->data_ep_pipe = 0;
-	}
-	if (info->sync_ep_pipe) {
-		ep = usb_pipe_endpoint(udev, info->sync_ep_pipe);
-		if (!ep)
-			pr_debug("%s: no sync ep\n", __func__);
-		else
-			usb_stop_endpoint(udev, ep);
-		info->sync_ep_pipe = 0;
-	}
-
 	uaudio_iommu_unmap(MEM_XFER_RING, info->data_xfer_ring_va,
 		info->data_xfer_ring_size, info->data_xfer_ring_size);
 	info->data_xfer_ring_va = 0;
@@ -987,6 +968,7 @@
 	struct snd_usb_audio *chip = NULL;
 	struct uaudio_qmi_svc *svc = uaudio_svc;
 	struct intf_info *info;
+	struct usb_host_endpoint *ep;
 	int pcm_format;
 	u8 pcm_card_num, pcm_dev_num, direction;
 	int info_idx = -EINVAL, ret = 0;
@@ -1057,6 +1039,29 @@
 	subs->cur_rate = req_msg->bit_rate;
 	uadev[pcm_card_num].ctrl_intf = chip->ctrl_intf;
 
+	if (!req_msg->enable) {
+		info = &uadev[pcm_card_num].info[info_idx];
+		if (info->data_ep_pipe) {
+			ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
+						info->data_ep_pipe);
+			if (!ep)
+				pr_debug("%s: no data ep\n", __func__);
+			else
+				usb_stop_endpoint(uadev[pcm_card_num].udev, ep);
+			info->data_ep_pipe = 0;
+		}
+
+		if (info->sync_ep_pipe) {
+			ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
+						info->sync_ep_pipe);
+			if (!ep)
+				pr_debug("%s: no sync ep\n", __func__);
+			else
+				usb_stop_endpoint(uadev[pcm_card_num].udev, ep);
+			info->sync_ep_pipe = 0;
+		}
+	}
+
 	ret = snd_usb_enable_audio_stream(subs, req_msg->enable);
 
 	if (!ret && req_msg->enable)