V4L/DVB: ivtv: Add firmare monitoring and debug mode to ignore firmware problems

>From Ian's e-mail:
When a device is opened the firmware state will be checked. If it isn't
responding then the open will fail with -EIO.  Due to the nature of the
hardware, a single failed check will block everything since we don't know
exactly what has failed. A side effect of this is the blocking of debug
access, so an additional debug level has been created which allows the block
to be bypassed.

Andy Walls' modifications:
I modified Ian's patch to add a separate fw_debug module parameter to change
the driver's behavior, as opposed to using the normal debug module parameter.
The fw_debug module parameter is only available when CONFIG_VIDEO_ADV_DEBUG
is set.
I also made some minor whitespace adjustments and changed some warning
messages to be a bit more specific.  s/happy/glad/g

Signed-off-by: Ian Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 3c2cc27..3fb21e1 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -32,6 +32,7 @@
 #include "ivtv-yuv.h"
 #include "ivtv-ioctl.h"
 #include "ivtv-cards.h"
+#include "ivtv-firmware.h"
 #include <media/v4l2-event.h>
 #include <media/saa7115.h>
 
@@ -526,6 +527,7 @@
 {
 	struct ivtv *itv = id->itv;
 	struct ivtv_stream *s = &itv->streams[id->type];
+	int rc;
 
 	if (atomic_read(&itv->decoding) == 0) {
 		if (ivtv_claim_stream(id, s->type)) {
@@ -533,7 +535,9 @@
 			IVTV_DEBUG_WARN("start decode, stream already claimed\n");
 			return -EBUSY;
 		}
-		ivtv_start_v4l2_decode_stream(s, 0);
+		rc = ivtv_start_v4l2_decode_stream(s, 0);
+		if (rc < 0)
+			return rc;
 	}
 	if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
 		return ivtv_set_speed(itv, speed);
@@ -912,12 +916,30 @@
 
 static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
 {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	struct video_device *vdev = video_devdata(filp);
+#endif
 	struct ivtv *itv = s->itv;
 	struct ivtv_open_id *item;
 	int res = 0;
 
 	IVTV_DEBUG_FILE("open %s\n", s->name);
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	if (ivtv_fw_debug) {
+		IVTV_WARN("Opening %s with dead firmware lockout disabled\n",
+			  video_device_node_name(vdev));
+		IVTV_WARN("Selected firmware errors will be ignored\n");
+	}
+
+	/* Unless ivtv_fw_debug is set, error out if firmware dead. */
+	if (ivtv_firmware_check(itv, "ivtv_serialized_open") && !ivtv_fw_debug)
+		return -EIO;
+#else
+	if (ivtv_firmware_check(itv, "ivtv_serialized_open"))
+		return -EIO;
+#endif
+
 	if (s->type == IVTV_DEC_STREAM_TYPE_MPG &&
 		test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
 		return -EBUSY;