[media] em28xx-audio: return -ENODEV when the device is disconnected

If em28xx is disconnected, return -ENODEV to all PCM callbacks.

Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c
index 13ba631..f3e3200 100644
--- a/drivers/media/usb/em28xx/em28xx-audio.c
+++ b/drivers/media/usb/em28xx/em28xx-audio.c
@@ -90,6 +90,12 @@
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_runtime   *runtime;
 
+	if (dev->disconnected) {
+		dprintk("device disconnected while streaming. URB status=%d.\n", urb->status);
+		atomic_set(&dev->stream_started, 0);
+		return;
+	}
+
 	switch (urb->status) {
 	case 0:             /* success */
 	case -ETIMEDOUT:    /* NAK */
@@ -248,14 +254,17 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int ret = 0;
 
-	dprintk("opening device and trying to acquire exclusive lock\n");
-
 	if (!dev) {
 		em28xx_err("BUG: em28xx can't find device struct."
 				" Can't proceed with open\n");
 		return -ENODEV;
 	}
 
+	if (dev->disconnected)
+		return -ENODEV;
+
+	dprintk("opening device and trying to acquire exclusive lock\n");
+
 	runtime->hw = snd_em28xx_hw_capture;
 	if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) {
 		int nonblock = !!(substream->f_flags & O_NONBLOCK);
@@ -324,6 +333,10 @@
 					struct snd_pcm_hw_params *hw_params)
 {
 	int ret;
+	struct em28xx *dev = snd_pcm_substream_chip(substream);
+
+	if (dev->disconnected)
+		return -ENODEV;
 
 	dprintk("Setting capture parameters\n");
 
@@ -363,6 +376,9 @@
 {
 	struct em28xx *dev = snd_pcm_substream_chip(substream);
 
+	if (dev->disconnected)
+		return -ENODEV;
+
 	dev->adev.hwptr_done_capture = 0;
 	dev->adev.capture_transfer_done = 0;
 
@@ -388,6 +404,9 @@
 	struct em28xx *dev = snd_pcm_substream_chip(substream);
 	int retval = 0;
 
+	if (dev->disconnected)
+		return -ENODEV;
+
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
 	case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
@@ -414,6 +433,9 @@
 	snd_pcm_uframes_t hwptr_done;
 
 	dev = snd_pcm_substream_chip(substream);
+	if (dev->disconnected)
+		return -ENODEV;
+
 	spin_lock_irqsave(&dev->adev.slock, flags);
 	hwptr_done = dev->adev.hwptr_done_capture;
 	spin_unlock_irqrestore(&dev->adev.slock, flags);
@@ -435,6 +457,11 @@
 static int em28xx_vol_info(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_info *info)
 {
+	struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+
+	if (dev->disconnected)
+		return -ENODEV;
+
 	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	info->count = 2;
 	info->value.integer.min = 0;
@@ -453,6 +480,9 @@
 	int nonblock = 0;
 	int rc;
 
+	if (dev->disconnected)
+		return -ENODEV;
+
 	if (substream)
 		nonblock = !!(substream->f_flags & O_NONBLOCK);
 	if (nonblock) {
@@ -488,6 +518,9 @@
 	int nonblock = 0;
 	int val;
 
+	if (dev->disconnected)
+		return -ENODEV;
+
 	if (substream)
 		nonblock = !!(substream->f_flags & O_NONBLOCK);
 	if (nonblock) {
@@ -520,6 +553,9 @@
 	int nonblock = 0;
 	int rc;
 
+	if (dev->disconnected)
+		return -ENODEV;
+
 	if (substream)
 		nonblock = !!(substream->f_flags & O_NONBLOCK);
 	if (nonblock) {
@@ -558,6 +594,9 @@
 	int nonblock = 0;
 	int val;
 
+	if (dev->disconnected)
+		return -ENODEV;
+
 	if (substream)
 		nonblock = !!(substream->f_flags & O_NONBLOCK);
 	if (nonblock) {