All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/6] [media] tda18271-fe: Fix support for ISDB-T
@ 2012-01-11  0:20 Mauro Carvalho Chehab
  2012-01-11  0:20 ` [PATCH 2/6] [media] cx231xx-input: stop polling if the device got removed Mauro Carvalho Chehab
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2012-01-11  0:20 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/common/tuners/tda18271-fe.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
index d3d91ea..7e30304 100644
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ b/drivers/media/common/tuners/tda18271-fe.c
@@ -946,6 +946,10 @@ static int tda18271_set_params(struct dvb_frontend *fe)
 		map = &std_map->atsc_6;
 		bw = 6000000;
 		break;
+	case SYS_ISDBT:
+		map = &std_map->dvbt_6;
+		bw = 6000000;
+		break;
 	case SYS_DVBT:
 	case SYS_DVBT2:
 		if (bw <= 6000000) {
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/6] [media] cx231xx-input: stop polling if the device got removed.
  2012-01-11  0:20 [PATCH 1/6] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab
@ 2012-01-11  0:20 ` Mauro Carvalho Chehab
  2012-01-11  0:20 ` [PATCH 3/6] [media] mb86a20s: implement get_frontend() Mauro Carvalho Chehab
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2012-01-11  0:20 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

If the device got removed, stops polling it. Also, un-registers
it at input/evdev, as it won't work anymore. We can't free the
IR structure yet, as the ir_remove method will be called later.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/video/cx231xx/cx231xx-input.c |    6 +++++-
 drivers/media/video/ir-kbd-i2c.c            |   17 +++++++++++++----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c
index 45e14ca..8a75a90 100644
--- a/drivers/media/video/cx231xx/cx231xx-input.c
+++ b/drivers/media/video/cx231xx/cx231xx-input.c
@@ -27,12 +27,16 @@
 static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
 			 u32 *ir_raw)
 {
+	int	rc;
 	u8	cmd, scancode;
 
 	dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__);
 
 		/* poll IR chip */
-	if (1 != i2c_master_recv(ir->c, &cmd, 1))
+	rc = i2c_master_recv(ir->c, &cmd, 1);
+	if (rc < 0)
+		return rc;
+	if (rc != 1)
 		return -EIO;
 
 	/* it seems that 0xFE indicates that a button is still hold
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 3ab875d..37d0c20 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -244,7 +244,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
 
 /* ----------------------------------------------------------------------- */
 
-static void ir_key_poll(struct IR_i2c *ir)
+static int ir_key_poll(struct IR_i2c *ir)
 {
 	static u32 ir_key, ir_raw;
 	int rc;
@@ -253,20 +253,28 @@ static void ir_key_poll(struct IR_i2c *ir)
 	rc = ir->get_key(ir, &ir_key, &ir_raw);
 	if (rc < 0) {
 		dprintk(2,"error\n");
-		return;
+		return rc;
 	}
 
 	if (rc) {
 		dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
 		rc_keydown(ir->rc, ir_key, 0);
 	}
+	return 0;
 }
 
 static void ir_work(struct work_struct *work)
 {
+	int rc;
 	struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work);
 
-	ir_key_poll(ir);
+	rc = ir_key_poll(ir);
+	if (rc == -ENODEV) {
+		rc_unregister_device(ir->rc);
+		ir->rc = NULL;
+		return;
+	}
+
 	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval));
 }
 
@@ -446,7 +454,8 @@ static int ir_remove(struct i2c_client *client)
 	cancel_delayed_work_sync(&ir->work);
 
 	/* unregister device */
-	rc_unregister_device(ir->rc);
+	if (ir->rc)
+		rc_unregister_device(ir->rc);
 
 	/* free memory */
 	kfree(ir);
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/6] [media] mb86a20s: implement get_frontend()
  2012-01-11  0:20 [PATCH 1/6] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab
  2012-01-11  0:20 ` [PATCH 2/6] [media] cx231xx-input: stop polling if the device got removed Mauro Carvalho Chehab
@ 2012-01-11  0:20 ` Mauro Carvalho Chehab
  2012-01-11  0:20 ` [PATCH 4/6] [media] cx231xx: Fix unregister logic Mauro Carvalho Chehab
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2012-01-11  0:20 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Reports the auto-detected parameters to userspace.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/dvb/frontends/mb86a20s.c |  196 +++++++++++++++++++++++++++++++-
 1 files changed, 193 insertions(+), 3 deletions(-)

diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c
index 82d3301..38778a8 100644
--- a/drivers/media/dvb/frontends/mb86a20s.c
+++ b/drivers/media/dvb/frontends/mb86a20s.c
@@ -525,16 +525,206 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe)
 	return rc;
 }
 
+static int mb86a20s_get_modulation(struct mb86a20s_state *state,
+				   unsigned layer)
+{
+	int rc;
+	static unsigned char reg[] = {
+		[0] = 0x86,	/* Layer A */
+		[1] = 0x8a,	/* Layer B */
+		[2] = 0x8e,	/* Layer C */
+	};
+
+	if (layer > ARRAY_SIZE(reg))
+		return -EINVAL;
+	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+	if (rc < 0)
+		return rc;
+	rc = mb86a20s_readreg(state, 0x6e);
+	if (rc < 0)
+		return rc;
+	switch ((rc & 0x70) >> 4) {
+	case 0:
+		return DQPSK;
+	case 1:
+		return QPSK;
+	case 2:
+		return QAM_16;
+	case 3:
+		return QAM_64;
+	default:
+		return QAM_AUTO;
+	}
+}
+
+static int mb86a20s_get_fec(struct mb86a20s_state *state,
+			    unsigned layer)
+{
+	int rc;
+
+	static unsigned char reg[] = {
+		[0] = 0x87,	/* Layer A */
+		[1] = 0x8b,	/* Layer B */
+		[2] = 0x8f,	/* Layer C */
+	};
+
+	if (layer > ARRAY_SIZE(reg))
+		return -EINVAL;
+	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+	if (rc < 0)
+		return rc;
+	rc = mb86a20s_readreg(state, 0x6e);
+	if (rc < 0)
+		return rc;
+	switch (rc) {
+	case 0:
+		return FEC_1_2;
+	case 1:
+		return FEC_2_3;
+	case 2:
+		return FEC_3_4;
+	case 3:
+		return FEC_5_6;
+	case 4:
+		return FEC_7_8;
+	default:
+		return FEC_AUTO;
+	}
+}
+
+static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
+				     unsigned layer)
+{
+	int rc;
+
+	static unsigned char reg[] = {
+		[0] = 0x88,	/* Layer A */
+		[1] = 0x8c,	/* Layer B */
+		[2] = 0x90,	/* Layer C */
+	};
+
+	if (layer > ARRAY_SIZE(reg))
+		return -EINVAL;
+	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+	if (rc < 0)
+		return rc;
+	rc = mb86a20s_readreg(state, 0x6e);
+	if (rc < 0)
+		return rc;
+	if (rc > 3)
+		return -EINVAL;	/* Not used */
+	return rc;
+}
+
+static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
+				      unsigned layer)
+{
+	int rc, count;
+
+	static unsigned char reg[] = {
+		[0] = 0x89,	/* Layer A */
+		[1] = 0x8d,	/* Layer B */
+		[2] = 0x91,	/* Layer C */
+	};
+
+	if (layer > ARRAY_SIZE(reg))
+		return -EINVAL;
+	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+	if (rc < 0)
+		return rc;
+	rc = mb86a20s_readreg(state, 0x6e);
+	if (rc < 0)
+		return rc;
+	count = (rc >> 4) & 0x0f;
+
+	return count;
+}
+
 static int mb86a20s_get_frontend(struct dvb_frontend *fe)
 {
+	struct mb86a20s_state *state = fe->demodulator_priv;
 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	int i, rc;
 
-	/* FIXME: For now, it does nothing */
-
+	/* Fixed parameters */
+	p->delivery_system = SYS_ISDBT;
 	p->bandwidth_hz = 6000000;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	/* Check for partial reception */
+	rc = mb86a20s_writereg(state, 0x6d, 0x85);
+	if (rc >= 0)
+		rc = mb86a20s_readreg(state, 0x6e);
+	if (rc >= 0)
+		p->isdbt_partial_reception = (rc & 0x10) ? 1 : 0;
+
+	/* Get per-layer data */
+	p->isdbt_layer_enabled = 0;
+	for (i = 0; i < 3; i++) {
+		rc = mb86a20s_get_segment_count(state, i);
+			if (rc >= 0 && rc < 14)
+				p->layer[i].segment_count = rc;
+		if (rc == 0x0f)
+			continue;
+		p->isdbt_layer_enabled |= 1 << i;
+		rc = mb86a20s_get_modulation(state, i);
+			if (rc >= 0)
+				p->layer[i].modulation = rc;
+		rc = mb86a20s_get_fec(state, i);
+			if (rc >= 0)
+				p->layer[i].fec = rc;
+		rc = mb86a20s_get_interleaving(state, i);
+			if (rc >= 0)
+				p->layer[i].interleaving = rc;
+	}
+
+	p->isdbt_sb_mode = 0;
+	rc = mb86a20s_writereg(state, 0x6d, 0x84);
+	if ((rc >= 0) && ((rc & 0x60) == 0x20)) {
+		p->isdbt_sb_mode = 1;
+		/* At least, one segment should exist */
+		if (!p->isdbt_sb_segment_count)
+			p->isdbt_sb_segment_count = 1;
+	} else
+		p->isdbt_sb_segment_count = 0;
+
+	/* Get transmission mode and guard interval */
 	p->transmission_mode = TRANSMISSION_MODE_AUTO;
 	p->guard_interval = GUARD_INTERVAL_AUTO;
-	p->isdbt_partial_reception = 0;
+	rc = mb86a20s_readreg(state, 0x07);
+	if (rc >= 0) {
+		if ((rc & 0x60) == 0x20) {
+			switch (rc & 0x0c >> 2) {
+			case 0:
+				p->transmission_mode = TRANSMISSION_MODE_2K;
+				break;
+			case 1:
+				p->transmission_mode = TRANSMISSION_MODE_4K;
+				break;
+			case 2:
+				p->transmission_mode = TRANSMISSION_MODE_8K;
+				break;
+			}
+		}
+		if (!(rc & 0x10)) {
+			switch (rc & 0x3) {
+			case 0:
+				p->guard_interval = GUARD_INTERVAL_1_4;
+				break;
+			case 1:
+				p->guard_interval = GUARD_INTERVAL_1_8;
+				break;
+			case 2:
+				p->guard_interval = GUARD_INTERVAL_1_16;
+				break;
+			}
+		}
+	}
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 
 	return 0;
 }
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/6] [media] cx231xx: Fix unregister logic
  2012-01-11  0:20 [PATCH 1/6] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab
  2012-01-11  0:20 ` [PATCH 2/6] [media] cx231xx-input: stop polling if the device got removed Mauro Carvalho Chehab
  2012-01-11  0:20 ` [PATCH 3/6] [media] mb86a20s: implement get_frontend() Mauro Carvalho Chehab
@ 2012-01-11  0:20 ` Mauro Carvalho Chehab
  2012-01-11  0:20 ` [PATCH 5/6] [media] cx231xx: cx231xx_devused is racy Mauro Carvalho Chehab
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2012-01-11  0:20 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

There are several weirdness at the unregister logic.

First of all, IR has a poll thread. This thread needs to be
removed, as it uses some resources associated to the main driver.
So, the driver needs to explicitly unregister the I2C client for
ir-kbd-i2c.

If, for some reason, the driver needs to wait for a close()
to happen, not all memories will be freed, because the free
logic were in the wrong place.

Also, v4l2_device_unregister() seems to be called too early,
as devices are still using it.

Finally, even with the device disconnected, there is one
USB function call that will still try to talk with it.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/video/cx231xx/cx231xx-cards.c |   29 ++++++++++++++------------
 drivers/media/video/cx231xx/cx231xx-core.c  |    3 ++
 drivers/media/video/cx231xx/cx231xx-input.c |    5 +++-
 drivers/media/video/cx231xx/cx231xx.h       |    1 +
 drivers/media/video/ir-kbd-i2c.c            |    8 -------
 5 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index 2a28882..bd82f01 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -843,15 +843,25 @@ void cx231xx_release_resources(struct cx231xx *dev)
 
 	cx231xx_remove_from_devlist(dev);
 
+	cx231xx_ir_exit(dev);
+
 	/* Release I2C buses */
 	cx231xx_dev_uninit(dev);
 
-	cx231xx_ir_exit(dev);
+	/* delete v4l2 device */
+	v4l2_device_unregister(&dev->v4l2_dev);
 
 	usb_put_dev(dev->udev);
 
 	/* Mark device as unused */
 	cx231xx_devused &= ~(1 << dev->devno);
+
+	kfree(dev->video_mode.alt_max_pkt_size);
+	kfree(dev->vbi_mode.alt_max_pkt_size);
+	kfree(dev->sliced_cc_mode.alt_max_pkt_size);
+	kfree(dev->ts1_mode.alt_max_pkt_size);
+	kfree(dev);
+	dev = NULL;
 }
 
 /*
@@ -1329,9 +1339,6 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
 
 	flush_request_modules(dev);
 
-	/* delete v4l2 device */
-	v4l2_device_unregister(&dev->v4l2_dev);
-
 	/* wait until all current v4l2 io is finished then deallocate
 	   resources */
 	mutex_lock(&dev->lock);
@@ -1344,6 +1351,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
 		     "deallocation are deferred on close.\n",
 		     video_device_node_name(dev->vdev));
 
+		/* Even having users, it is safe to remove the RC i2c driver */
+		cx231xx_ir_exit(dev);
+
 		dev->state |= DEV_MISCONFIGURED;
 		if (dev->USE_ISO)
 			cx231xx_uninit_isoc(dev);
@@ -1354,21 +1364,14 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
 		wake_up_interruptible(&dev->wait_stream);
 	} else {
 		dev->state |= DEV_DISCONNECTED;
-		cx231xx_release_resources(dev);
 	}
 
 	cx231xx_close_extension(dev);
 
 	mutex_unlock(&dev->lock);
 
-	if (!dev->users) {
-		kfree(dev->video_mode.alt_max_pkt_size);
-		kfree(dev->vbi_mode.alt_max_pkt_size);
-		kfree(dev->sliced_cc_mode.alt_max_pkt_size);
-		kfree(dev->ts1_mode.alt_max_pkt_size);
-		kfree(dev);
-		dev = NULL;
-	}
+	if (!dev->users)
+		cx231xx_release_resources(dev);
 }
 
 static struct usb_driver cx231xx_usb_driver = {
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c
index d4457f9..39e9878 100644
--- a/drivers/media/video/cx231xx/cx231xx-core.c
+++ b/drivers/media/video/cx231xx/cx231xx-core.c
@@ -166,6 +166,9 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
 	u8 _i2c_nostop = 0;
 	u8 _i2c_reserve = 0;
 
+	if (dev->state & DEV_DISCONNECTED)
+		return -ENODEV;
+
 	/* Get the I2C period, nostop and reserve parameters */
 	_i2c_period = i2c_bus->i2c_period;
 	_i2c_nostop = i2c_bus->i2c_nostop;
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c
index 8a75a90..96176e9 100644
--- a/drivers/media/video/cx231xx/cx231xx-input.c
+++ b/drivers/media/video/cx231xx/cx231xx-input.c
@@ -106,11 +106,14 @@ int cx231xx_ir_init(struct cx231xx *dev)
 	ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master;
 	dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
 		ir_i2c_bus, info.addr);
-	i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
+	dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
 
 	return 0;
 }
 
 void cx231xx_ir_exit(struct cx231xx *dev)
 {
+	if (dev->ir_i2c_client)
+		i2c_unregister_device(dev->ir_i2c_client);
+	dev->ir_i2c_client = NULL;
 }
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h
index 2000bc6..5d498a4 100644
--- a/drivers/media/video/cx231xx/cx231xx.h
+++ b/drivers/media/video/cx231xx/cx231xx.h
@@ -621,6 +621,7 @@ struct cx231xx {
 
 	/* For I2C IR support */
 	struct IR_i2c_init_data    init_data;
+	struct i2c_client          *ir_i2c_client;
 
 	unsigned int stream_on:1;	/* Locks streams */
 	unsigned int vbi_stream_on:1;	/* Locks streams for VBI */
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 37d0c20..a7c41d3 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -498,11 +498,3 @@ static void __exit ir_fini(void)
 
 module_init(ir_init);
 module_exit(ir_fini);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/6] [media] cx231xx: cx231xx_devused is racy
  2012-01-11  0:20 [PATCH 1/6] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab
                   ` (2 preceding siblings ...)
  2012-01-11  0:20 ` [PATCH 4/6] [media] cx231xx: Fix unregister logic Mauro Carvalho Chehab
@ 2012-01-11  0:20 ` Mauro Carvalho Chehab
  2012-01-11  0:20 ` [PATCH 6/6] [media] cx231xx: fix device disconnect checks Mauro Carvalho Chehab
  2012-01-11  0:37 ` [PATCH v2] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab
  5 siblings, 0 replies; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2012-01-11  0:20 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

cx231xx_devused is racy. Re-implement it in a proper way,
to remove the risk of mangling it.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/video/cx231xx/cx231xx-cards.c |   36 +++++++++++++-------------
 1 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index bd82f01..1f2fbbf 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -854,7 +854,7 @@ void cx231xx_release_resources(struct cx231xx *dev)
 	usb_put_dev(dev->udev);
 
 	/* Mark device as unused */
-	cx231xx_devused &= ~(1 << dev->devno);
+	clear_bit(dev->devno, &cx231xx_devused);
 
 	kfree(dev->video_mode.alt_max_pkt_size);
 	kfree(dev->vbi_mode.alt_max_pkt_size);
@@ -1039,21 +1039,21 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 		return -ENODEV;
 
 	/* Check to see next free device and mark as used */
-	nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
-	cx231xx_devused |= 1 << nr;
-
-	if (nr >= CX231XX_MAXBOARDS) {
-		cx231xx_err(DRIVER_NAME
-		 ": Supports only %i cx231xx boards.\n", CX231XX_MAXBOARDS);
-		cx231xx_devused &= ~(1 << nr);
-		return -ENOMEM;
-	}
+	do {
+		nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
+		if (nr >= CX231XX_MAXBOARDS) {
+			/* No free device slots */
+			cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n",
+					CX231XX_MAXBOARDS);
+			return -ENOMEM;
+		}
+	} while (test_and_set_bit(nr, &cx231xx_devused));
 
 	/* allocate memory for our device state and initialize it */
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
 		cx231xx_err(DRIVER_NAME ": out of memory!\n");
-		cx231xx_devused &= ~(1 << nr);
+		clear_bit(dev->devno, &cx231xx_devused);
 		return -ENOMEM;
 	}
 
@@ -1129,7 +1129,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 	if (assoc_desc->bFirstInterface != ifnum) {
 		cx231xx_err(DRIVER_NAME ": Not found "
 			    "matching IAD interface\n");
-		cx231xx_devused &= ~(1 << nr);
+		clear_bit(dev->devno, &cx231xx_devused);
 		kfree(dev);
 		dev = NULL;
 		return -ENODEV;
@@ -1148,7 +1148,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 	retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
 	if (retval) {
 		cx231xx_errdev("v4l2_device_register failed\n");
-		cx231xx_devused &= ~(1 << nr);
+		clear_bit(dev->devno, &cx231xx_devused);
 		kfree(dev);
 		dev = NULL;
 		return -EIO;
@@ -1156,7 +1156,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 	/* allocate device struct */
 	retval = cx231xx_init_dev(&dev, udev, nr);
 	if (retval) {
-		cx231xx_devused &= ~(1 << dev->devno);
+		clear_bit(dev->devno, &cx231xx_devused);
 		v4l2_device_unregister(&dev->v4l2_dev);
 		kfree(dev);
 		dev = NULL;
@@ -1181,7 +1181,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 
 	if (dev->video_mode.alt_max_pkt_size == NULL) {
 		cx231xx_errdev("out of memory!\n");
-		cx231xx_devused &= ~(1 << nr);
+		clear_bit(dev->devno, &cx231xx_devused);
 		v4l2_device_unregister(&dev->v4l2_dev);
 		kfree(dev);
 		dev = NULL;
@@ -1215,7 +1215,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 
 	if (dev->vbi_mode.alt_max_pkt_size == NULL) {
 		cx231xx_errdev("out of memory!\n");
-		cx231xx_devused &= ~(1 << nr);
+		clear_bit(dev->devno, &cx231xx_devused);
 		v4l2_device_unregister(&dev->v4l2_dev);
 		kfree(dev);
 		dev = NULL;
@@ -1250,7 +1250,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 
 	if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
 		cx231xx_errdev("out of memory!\n");
-		cx231xx_devused &= ~(1 << nr);
+		clear_bit(dev->devno, &cx231xx_devused);
 		v4l2_device_unregister(&dev->v4l2_dev);
 		kfree(dev);
 		dev = NULL;
@@ -1286,7 +1286,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
 
 		if (dev->ts1_mode.alt_max_pkt_size == NULL) {
 			cx231xx_errdev("out of memory!\n");
-			cx231xx_devused &= ~(1 << nr);
+			clear_bit(dev->devno, &cx231xx_devused);
 			v4l2_device_unregister(&dev->v4l2_dev);
 			kfree(dev);
 			dev = NULL;
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/6] [media] cx231xx: fix device disconnect checks
  2012-01-11  0:20 [PATCH 1/6] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab
                   ` (3 preceding siblings ...)
  2012-01-11  0:20 ` [PATCH 5/6] [media] cx231xx: cx231xx_devused is racy Mauro Carvalho Chehab
@ 2012-01-11  0:20 ` Mauro Carvalho Chehab
  2012-01-11  0:37 ` [PATCH v2] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab
  5 siblings, 0 replies; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2012-01-11  0:20 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

The driver were using DEV_MISCONFIGURED on some places, and
DEV_DISCONNECTED on others. In a matter of fact, DEV_MISCONFIGURED
were set only during the usb disconnect callback, with
was confusing.

Also, the alsa driver never checks if the device is present,
before doing some dangerous things.

Remove DEV_MISCONFIGURED, replacing it by DEV_DISCONNECTED.

Also, fixes the other usecases for DEV_DISCONNECTED.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/video/cx231xx/cx231xx-audio.c |   20 ++++++++++++++++++++
 drivers/media/video/cx231xx/cx231xx-cards.c |    5 ++---
 drivers/media/video/cx231xx/cx231xx-dvb.c   |    4 ++--
 drivers/media/video/cx231xx/cx231xx-vbi.c   |    2 +-
 drivers/media/video/cx231xx/cx231xx-video.c |   14 ++++----------
 drivers/media/video/cx231xx/cx231xx.h       |    1 -
 6 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c
index 30d13c1..e5742a0 100644
--- a/drivers/media/video/cx231xx/cx231xx-audio.c
+++ b/drivers/media/video/cx231xx/cx231xx-audio.c
@@ -111,6 +111,9 @@ static void cx231xx_audio_isocirq(struct urb *urb)
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_runtime *runtime;
 
+	if (dev->state & DEV_DISCONNECTED)
+		return;
+
 	switch (urb->status) {
 	case 0:		/* success */
 	case -ETIMEDOUT:	/* NAK */
@@ -196,6 +199,9 @@ static void cx231xx_audio_bulkirq(struct urb *urb)
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_runtime *runtime;
 
+	if (dev->state & DEV_DISCONNECTED)
+		return;
+
 	switch (urb->status) {
 	case 0:		/* success */
 	case -ETIMEDOUT:	/* NAK */
@@ -273,6 +279,9 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev)
 
 	cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__);
 
+	if (dev->state & DEV_DISCONNECTED)
+		return -ENODEV;
+
 	sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
 
 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
@@ -331,6 +340,9 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev)
 
 	cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__);
 
+	if (dev->state & DEV_DISCONNECTED)
+		return -ENODEV;
+
 	sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
 
 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
@@ -432,6 +444,11 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
 		return -ENODEV;
 	}
 
+	if (dev->state & DEV_DISCONNECTED) {
+		cx231xx_errdev("Can't open. the device was removed.\n");
+		return -ENODEV;
+	}
+
 	/* Sets volume, mute, etc */
 	dev->mute = 0;
 
@@ -571,6 +588,9 @@ static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream,
 	struct cx231xx *dev = snd_pcm_substream_chip(substream);
 	int retval;
 
+	if (dev->state & DEV_DISCONNECTED)
+		return -ENODEV;
+
 	spin_lock(&dev->adev.slock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index 1f2fbbf..7577e6e 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -1337,6 +1337,8 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
 	if (!dev->udev)
 		return;
 
+	dev->state |= DEV_DISCONNECTED;
+
 	flush_request_modules(dev);
 
 	/* wait until all current v4l2 io is finished then deallocate
@@ -1354,16 +1356,13 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
 		/* Even having users, it is safe to remove the RC i2c driver */
 		cx231xx_ir_exit(dev);
 
-		dev->state |= DEV_MISCONFIGURED;
 		if (dev->USE_ISO)
 			cx231xx_uninit_isoc(dev);
 		else
 			cx231xx_uninit_bulk(dev);
-		dev->state |= DEV_DISCONNECTED;
 		wake_up_interruptible(&dev->wait_frame);
 		wake_up_interruptible(&dev->wait_stream);
 	} else {
-		dev->state |= DEV_DISCONNECTED;
 	}
 
 	cx231xx_close_extension(dev);
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c
index da9a4a0..7c4e360 100644
--- a/drivers/media/video/cx231xx/cx231xx-dvb.c
+++ b/drivers/media/video/cx231xx/cx231xx-dvb.c
@@ -196,7 +196,7 @@ static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
 	if (!dev)
 		return 0;
 
-	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+	if (dev->state & DEV_DISCONNECTED)
 		return 0;
 
 	if (urb->status < 0) {
@@ -228,7 +228,7 @@ static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)
 	if (!dev)
 		return 0;
 
-	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+	if (dev->state & DEV_DISCONNECTED)
 		return 0;
 
 	if (urb->status < 0) {
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c
index 1c7a4da..9c5967e 100644
--- a/drivers/media/video/cx231xx/cx231xx-vbi.c
+++ b/drivers/media/video/cx231xx/cx231xx-vbi.c
@@ -93,7 +93,7 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb)
 	if (!dev)
 		return 0;
 
-	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+	if (dev->state & DEV_DISCONNECTED)
 		return 0;
 
 	if (urb->status < 0) {
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
index 6e81f97..829a41b 100644
--- a/drivers/media/video/cx231xx/cx231xx-video.c
+++ b/drivers/media/video/cx231xx/cx231xx-video.c
@@ -337,7 +337,7 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
 	if (!dev)
 		return 0;
 
-	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+	if (dev->state & DEV_DISCONNECTED)
 		return 0;
 
 	if (urb->status < 0) {
@@ -440,7 +440,7 @@ static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
 	if (!dev)
 		return 0;
 
-	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+	if (dev->state & DEV_DISCONNECTED)
 		return 0;
 
 	if (urb->status < 0) {
@@ -1000,12 +1000,6 @@ static int check_dev(struct cx231xx *dev)
 		cx231xx_errdev("v4l2 ioctl: device not present\n");
 		return -ENODEV;
 	}
-
-	if (dev->state & DEV_MISCONFIGURED) {
-		cx231xx_errdev("v4l2 ioctl: device is misconfigured; "
-			       "close and open it again\n");
-		return -EIO;
-	}
 	return 0;
 }
 
@@ -2347,7 +2341,8 @@ static int cx231xx_v4l2_close(struct file *filp)
 			return 0;
 		}
 
-	if (dev->users == 1) {
+	dev->users--;
+	if (!dev->users) {
 		videobuf_stop(&fh->vb_vidq);
 		videobuf_mmap_free(&fh->vb_vidq);
 
@@ -2374,7 +2369,6 @@ static int cx231xx_v4l2_close(struct file *filp)
 		cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
 	}
 	kfree(fh);
-	dev->users--;
 	wake_up_interruptible_nr(&dev->open, 1);
 	return 0;
 }
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h
index 5d498a4..e174475 100644
--- a/drivers/media/video/cx231xx/cx231xx.h
+++ b/drivers/media/video/cx231xx/cx231xx.h
@@ -377,7 +377,6 @@ struct cx231xx_board {
 enum cx231xx_dev_state {
 	DEV_INITIALIZED = 0x01,
 	DEV_DISCONNECTED = 0x02,
-	DEV_MISCONFIGURED = 0x04,
 };
 
 enum AFE_MODE {
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2] [media] tda18271-fe: Fix support for ISDB-T
  2012-01-11  0:20 [PATCH 1/6] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab
                   ` (4 preceding siblings ...)
  2012-01-11  0:20 ` [PATCH 6/6] [media] cx231xx: fix device disconnect checks Mauro Carvalho Chehab
@ 2012-01-11  0:37 ` Mauro Carvalho Chehab
  5 siblings, 0 replies; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2012-01-11  0:37 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---

V2: ISDB-T can use 6, 7 or 8MHz for bandwidth. So, the code should
handle it just like DVB-T.

 drivers/media/common/tuners/tda18271-fe.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
index d3d91ea..2e67f44 100644
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ b/drivers/media/common/tuners/tda18271-fe.c
@@ -946,6 +946,7 @@ static int tda18271_set_params(struct dvb_frontend *fe)
 		map = &std_map->atsc_6;
 		bw = 6000000;
 		break;
+	case SYS_ISDBT:
 	case SYS_DVBT:
 	case SYS_DVBT2:
 		if (bw <= 6000000) {
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-01-11  0:37 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-11  0:20 [PATCH 1/6] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab
2012-01-11  0:20 ` [PATCH 2/6] [media] cx231xx-input: stop polling if the device got removed Mauro Carvalho Chehab
2012-01-11  0:20 ` [PATCH 3/6] [media] mb86a20s: implement get_frontend() Mauro Carvalho Chehab
2012-01-11  0:20 ` [PATCH 4/6] [media] cx231xx: Fix unregister logic Mauro Carvalho Chehab
2012-01-11  0:20 ` [PATCH 5/6] [media] cx231xx: cx231xx_devused is racy Mauro Carvalho Chehab
2012-01-11  0:20 ` [PATCH 6/6] [media] cx231xx: fix device disconnect checks Mauro Carvalho Chehab
2012-01-11  0:37 ` [PATCH v2] [media] tda18271-fe: Fix support for ISDB-T Mauro Carvalho Chehab

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.