Commit e8e3039f authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[media] au0828: Fix dev_state handling

The au0828 dev_state is actually a bit mask. It should not be
checking with "==" but, instead, with a logic and. There are some
places where it was doing it wrong.

Fix that by replacing the dev_state set/clear/test with the
bitops.

As reviewed by Shuah:
	"Looks good. Tested running bind/unbind au0828 loop for 1000 times.
	Didn't see any problems and the v4l2_querycap() problem has been
	fixed with this patch.

	After the above test, ran bind/unbind snd_usb_audio 1000 times.
	Didn't see any problems. Generated media graph and the graph
	looks good."

Cc: stable@vger.kernel.org
Reviewed-by: default avatarShuah Khan <shuahkh@osg.samsung.com>
Tested-by: default avatarShuah Khan <shuahkh@osg.samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent ed940cd2
...@@ -171,7 +171,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) ...@@ -171,7 +171,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
Set the status so poll routines can check and avoid Set the status so poll routines can check and avoid
access after disconnect. access after disconnect.
*/ */
dev->dev_state = DEV_DISCONNECTED; set_bit(DEV_DISCONNECTED, &dev->dev_state);
au0828_rc_unregister(dev); au0828_rc_unregister(dev);
/* Digital TV */ /* Digital TV */
......
...@@ -130,7 +130,7 @@ static int au0828_get_key_au8522(struct au0828_rc *ir) ...@@ -130,7 +130,7 @@ static int au0828_get_key_au8522(struct au0828_rc *ir)
bool first = true; bool first = true;
/* do nothing if device is disconnected */ /* do nothing if device is disconnected */
if (ir->dev->dev_state == DEV_DISCONNECTED) if (test_bit(DEV_DISCONNECTED, &ir->dev->dev_state))
return 0; return 0;
/* Check IR int */ /* Check IR int */
...@@ -260,7 +260,7 @@ static void au0828_rc_stop(struct rc_dev *rc) ...@@ -260,7 +260,7 @@ static void au0828_rc_stop(struct rc_dev *rc)
cancel_delayed_work_sync(&ir->work); cancel_delayed_work_sync(&ir->work);
/* do nothing if device is disconnected */ /* do nothing if device is disconnected */
if (ir->dev->dev_state != DEV_DISCONNECTED) { if (!test_bit(DEV_DISCONNECTED, &ir->dev->dev_state)) {
/* Disable IR */ /* Disable IR */
au8522_rc_clear(ir, 0xe0, 1 << 4); au8522_rc_clear(ir, 0xe0, 1 << 4);
} }
......
...@@ -106,14 +106,13 @@ static inline void print_err_status(struct au0828_dev *dev, ...@@ -106,14 +106,13 @@ static inline void print_err_status(struct au0828_dev *dev,
static int check_dev(struct au0828_dev *dev) static int check_dev(struct au0828_dev *dev)
{ {
if (dev->dev_state & DEV_DISCONNECTED) { if (test_bit(DEV_DISCONNECTED, &dev->dev_state)) {
pr_info("v4l2 ioctl: device not present\n"); pr_info("v4l2 ioctl: device not present\n");
return -ENODEV; return -ENODEV;
} }
if (dev->dev_state & DEV_MISCONFIGURED) { if (test_bit(DEV_MISCONFIGURED, &dev->dev_state)) {
pr_info("v4l2 ioctl: device is misconfigured; " pr_info("v4l2 ioctl: device is misconfigured; close and open it again\n");
"close and open it again\n");
return -EIO; return -EIO;
} }
return 0; return 0;
...@@ -521,8 +520,8 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) ...@@ -521,8 +520,8 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
if (!dev) if (!dev)
return 0; return 0;
if ((dev->dev_state & DEV_DISCONNECTED) || if (test_bit(DEV_DISCONNECTED, &dev->dev_state) ||
(dev->dev_state & DEV_MISCONFIGURED)) test_bit(DEV_MISCONFIGURED, &dev->dev_state))
return 0; return 0;
if (urb->status < 0) { if (urb->status < 0) {
...@@ -824,10 +823,10 @@ static int au0828_stream_interrupt(struct au0828_dev *dev) ...@@ -824,10 +823,10 @@ static int au0828_stream_interrupt(struct au0828_dev *dev)
int ret = 0; int ret = 0;
dev->stream_state = STREAM_INTERRUPT; dev->stream_state = STREAM_INTERRUPT;
if (dev->dev_state == DEV_DISCONNECTED) if (test_bit(DEV_DISCONNECTED, &dev->dev_state))
return -ENODEV; return -ENODEV;
else if (ret) { else if (ret) {
dev->dev_state = DEV_MISCONFIGURED; set_bit(DEV_MISCONFIGURED, &dev->dev_state);
dprintk(1, "%s device is misconfigured!\n", __func__); dprintk(1, "%s device is misconfigured!\n", __func__);
return ret; return ret;
} }
...@@ -1026,7 +1025,7 @@ static int au0828_v4l2_open(struct file *filp) ...@@ -1026,7 +1025,7 @@ static int au0828_v4l2_open(struct file *filp)
int ret; int ret;
dprintk(1, dprintk(1,
"%s called std_set %d dev_state %d stream users %d users %d\n", "%s called std_set %d dev_state %ld stream users %d users %d\n",
__func__, dev->std_set_in_tuner_core, dev->dev_state, __func__, dev->std_set_in_tuner_core, dev->dev_state,
dev->streaming_users, dev->users); dev->streaming_users, dev->users);
...@@ -1045,7 +1044,7 @@ static int au0828_v4l2_open(struct file *filp) ...@@ -1045,7 +1044,7 @@ static int au0828_v4l2_open(struct file *filp)
au0828_analog_stream_enable(dev); au0828_analog_stream_enable(dev);
au0828_analog_stream_reset(dev); au0828_analog_stream_reset(dev);
dev->stream_state = STREAM_OFF; dev->stream_state = STREAM_OFF;
dev->dev_state |= DEV_INITIALIZED; set_bit(DEV_INITIALIZED, &dev->dev_state);
} }
dev->users++; dev->users++;
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
...@@ -1059,7 +1058,7 @@ static int au0828_v4l2_close(struct file *filp) ...@@ -1059,7 +1058,7 @@ static int au0828_v4l2_close(struct file *filp)
struct video_device *vdev = video_devdata(filp); struct video_device *vdev = video_devdata(filp);
dprintk(1, dprintk(1,
"%s called std_set %d dev_state %d stream users %d users %d\n", "%s called std_set %d dev_state %ld stream users %d users %d\n",
__func__, dev->std_set_in_tuner_core, dev->dev_state, __func__, dev->std_set_in_tuner_core, dev->dev_state,
dev->streaming_users, dev->users); dev->streaming_users, dev->users);
...@@ -1075,7 +1074,7 @@ static int au0828_v4l2_close(struct file *filp) ...@@ -1075,7 +1074,7 @@ static int au0828_v4l2_close(struct file *filp)
del_timer_sync(&dev->vbi_timeout); del_timer_sync(&dev->vbi_timeout);
} }
if (dev->dev_state & DEV_DISCONNECTED) if (test_bit(DEV_DISCONNECTED, &dev->dev_state))
goto end; goto end;
if (dev->users == 1) { if (dev->users == 1) {
...@@ -1135,7 +1134,7 @@ static void au0828_init_tuner(struct au0828_dev *dev) ...@@ -1135,7 +1134,7 @@ static void au0828_init_tuner(struct au0828_dev *dev)
.type = V4L2_TUNER_ANALOG_TV, .type = V4L2_TUNER_ANALOG_TV,
}; };
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
if (dev->std_set_in_tuner_core) if (dev->std_set_in_tuner_core)
...@@ -1207,7 +1206,7 @@ static int vidioc_querycap(struct file *file, void *priv, ...@@ -1207,7 +1206,7 @@ static int vidioc_querycap(struct file *file, void *priv,
struct video_device *vdev = video_devdata(file); struct video_device *vdev = video_devdata(file);
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
strlcpy(cap->driver, "au0828", sizeof(cap->driver)); strlcpy(cap->driver, "au0828", sizeof(cap->driver));
...@@ -1250,7 +1249,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, ...@@ -1250,7 +1249,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
{ {
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
f->fmt.pix.width = dev->width; f->fmt.pix.width = dev->width;
...@@ -1269,7 +1268,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, ...@@ -1269,7 +1268,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
{ {
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
return au0828_set_format(dev, VIDIOC_TRY_FMT, f); return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
...@@ -1281,7 +1280,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -1281,7 +1280,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
int rc; int rc;
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
rc = check_dev(dev); rc = check_dev(dev);
...@@ -1303,7 +1302,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) ...@@ -1303,7 +1302,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
{ {
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
if (norm == dev->std) if (norm == dev->std)
...@@ -1335,7 +1334,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) ...@@ -1335,7 +1334,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
{ {
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
*norm = dev->std; *norm = dev->std;
...@@ -1357,7 +1356,7 @@ static int vidioc_enum_input(struct file *file, void *priv, ...@@ -1357,7 +1356,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
[AU0828_VMUX_DVB] = "DVB", [AU0828_VMUX_DVB] = "DVB",
}; };
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
tmp = input->index; tmp = input->index;
...@@ -1387,7 +1386,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) ...@@ -1387,7 +1386,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{ {
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
*i = dev->ctrl_input; *i = dev->ctrl_input;
...@@ -1398,7 +1397,7 @@ static void au0828_s_input(struct au0828_dev *dev, int index) ...@@ -1398,7 +1397,7 @@ static void au0828_s_input(struct au0828_dev *dev, int index)
{ {
int i; int i;
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
switch (AUVI_INPUT(index).type) { switch (AUVI_INPUT(index).type) {
...@@ -1496,7 +1495,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) ...@@ -1496,7 +1495,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
{ {
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
a->index = dev->ctrl_ainput; a->index = dev->ctrl_ainput;
...@@ -1516,7 +1515,7 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio ...@@ -1516,7 +1515,7 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio
if (a->index != dev->ctrl_ainput) if (a->index != dev->ctrl_ainput)
return -EINVAL; return -EINVAL;
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
return 0; return 0;
} }
...@@ -1534,7 +1533,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) ...@@ -1534,7 +1533,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
if (ret) if (ret)
return ret; return ret;
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
strcpy(t->name, "Auvitek tuner"); strcpy(t->name, "Auvitek tuner");
...@@ -1554,7 +1553,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, ...@@ -1554,7 +1553,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
if (t->index != 0) if (t->index != 0)
return -EINVAL; return -EINVAL;
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
au0828_init_tuner(dev); au0828_init_tuner(dev);
...@@ -1576,7 +1575,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, ...@@ -1576,7 +1575,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
if (freq->tuner != 0) if (freq->tuner != 0)
return -EINVAL; return -EINVAL;
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
freq->frequency = dev->ctrl_freq; freq->frequency = dev->ctrl_freq;
return 0; return 0;
...@@ -1591,7 +1590,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, ...@@ -1591,7 +1590,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
if (freq->tuner != 0) if (freq->tuner != 0)
return -EINVAL; return -EINVAL;
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
au0828_init_tuner(dev); au0828_init_tuner(dev);
...@@ -1617,7 +1616,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, ...@@ -1617,7 +1616,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
{ {
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
format->fmt.vbi.samples_per_line = dev->vbi_width; format->fmt.vbi.samples_per_line = dev->vbi_width;
...@@ -1643,7 +1642,7 @@ static int vidioc_cropcap(struct file *file, void *priv, ...@@ -1643,7 +1642,7 @@ static int vidioc_cropcap(struct file *file, void *priv,
if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
cc->bounds.left = 0; cc->bounds.left = 0;
...@@ -1665,7 +1664,7 @@ static int vidioc_g_register(struct file *file, void *priv, ...@@ -1665,7 +1664,7 @@ static int vidioc_g_register(struct file *file, void *priv,
{ {
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
reg->val = au0828_read(dev, reg->reg); reg->val = au0828_read(dev, reg->reg);
...@@ -1678,7 +1677,7 @@ static int vidioc_s_register(struct file *file, void *priv, ...@@ -1678,7 +1677,7 @@ static int vidioc_s_register(struct file *file, void *priv,
{ {
struct au0828_dev *dev = video_drvdata(file); struct au0828_dev *dev = video_drvdata(file);
dprintk(1, "%s called std_set %d dev_state %d\n", __func__, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__,
dev->std_set_in_tuner_core, dev->dev_state); dev->std_set_in_tuner_core, dev->dev_state);
return au0828_writereg(dev, reg->reg, reg->val); return au0828_writereg(dev, reg->reg, reg->val);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bitops.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
...@@ -121,9 +122,9 @@ enum au0828_stream_state { ...@@ -121,9 +122,9 @@ enum au0828_stream_state {
/* device state */ /* device state */
enum au0828_dev_state { enum au0828_dev_state {
DEV_INITIALIZED = 0x01, DEV_INITIALIZED = 0,
DEV_DISCONNECTED = 0x02, DEV_DISCONNECTED = 1,
DEV_MISCONFIGURED = 0x04 DEV_MISCONFIGURED = 2
}; };
struct au0828_dev; struct au0828_dev;
...@@ -247,7 +248,7 @@ struct au0828_dev { ...@@ -247,7 +248,7 @@ struct au0828_dev {
int input_type; int input_type;
int std_set_in_tuner_core; int std_set_in_tuner_core;
unsigned int ctrl_input; unsigned int ctrl_input;
enum au0828_dev_state dev_state; long unsigned int dev_state; /* defined at enum au0828_dev_state */;
enum au0828_stream_state stream_state; enum au0828_stream_state stream_state;
wait_queue_head_t open; wait_queue_head_t open;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment