summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb.h5
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c53
2 files changed, 41 insertions, 17 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
index 42801f8ecaa8..658c6d47fdff 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
@@ -329,13 +329,16 @@ struct dvb_usb_adapter {
u8 feed_count;
u8 max_feed_count;
s8 active_fe;
+#define ADAP_INIT 0
+#define ADAP_SLEEP 1
+#define ADAP_STREAMING 2
+ unsigned long state_bits;
/* dvb */
struct dvb_adapter dvb_adap;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dvb_net dvb_net;
- struct mutex sync_mutex;
struct dvb_frontend *fe[MAX_NO_OF_FE_PER_ADAP];
int (*fe_init[MAX_NO_OF_FE_PER_ADAP]) (struct dvb_frontend *);
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index 086792055912..c91da3c4d332 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -253,6 +253,13 @@ static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
return usb_urb_exitv2(&adap->stream);
}
+static int wait_schedule(void *ptr)
+{
+ schedule();
+
+ return 0;
+}
+
static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
int count)
{
@@ -266,6 +273,9 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
dvbdmxfeed->pid, dvbdmxfeed->index,
(count == 1) ? "on" : "off");
+ wait_on_bit(&adap->state_bits, ADAP_INIT, wait_schedule,
+ TASK_UNINTERRUPTIBLE);
+
if (adap->active_fe == -1)
return -EINVAL;
@@ -283,11 +293,14 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
"failed=%d\n", KBUILD_MODNAME,
ret);
usb_urb_killv2(&adap->stream);
- goto err_mutex_unlock;
+ goto err_clear_wait;
}
}
usb_urb_killv2(&adap->stream);
- mutex_unlock(&adap->sync_mutex);
+
+ clear_bit(ADAP_STREAMING, &adap->state_bits);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&adap->state_bits, ADAP_STREAMING);
}
/* activate the pid on the device pid filter */
@@ -303,7 +316,7 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
/* start feeding if it is first pid */
if (adap->feed_count == 1 && count == 1) {
struct usb_data_stream_properties stream_props;
- mutex_lock(&adap->sync_mutex);
+ set_bit(ADAP_STREAMING, &adap->state_bits);
dev_dbg(&d->udev->dev, "%s: start feeding\n", __func__);
/* resolve input and output streaming paramters */
@@ -314,7 +327,7 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
adap->fe[adap->active_fe],
&adap->ts_type, &stream_props);
if (ret < 0)
- goto err_mutex_unlock;
+ goto err_clear_wait;
} else {
stream_props = adap->props->stream;
}
@@ -344,7 +357,7 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
dev_err(&d->udev->dev, "%s: " \
"pid_filter_ctrl() failed=%d\n",
KBUILD_MODNAME, ret);
- goto err_mutex_unlock;
+ goto err_clear_wait;
}
}
@@ -355,14 +368,16 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
dev_err(&d->udev->dev, "%s: streaming_ctrl() " \
"failed=%d\n", KBUILD_MODNAME,
ret);
- goto err_mutex_unlock;
+ goto err_clear_wait;
}
}
}
return 0;
-err_mutex_unlock:
- mutex_unlock(&adap->sync_mutex);
+err_clear_wait:
+ clear_bit(ADAP_STREAMING, &adap->state_bits);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&adap->state_bits, ADAP_STREAMING);
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -435,8 +450,6 @@ static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
goto err_dvb_net_init;
}
- mutex_init(&adap->sync_mutex);
-
return 0;
err_dvb_net_init:
dvb_dmxdev_release(&adap->dmxdev);
@@ -500,7 +513,7 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
if (!adap->suspend_resume_active) {
adap->active_fe = fe->id;
- mutex_lock(&adap->sync_mutex);
+ set_bit(ADAP_INIT, &adap->state_bits);
}
ret = dvb_usbv2_device_power_ctrl(d, 1);
@@ -519,8 +532,11 @@ static int dvb_usb_fe_init(struct dvb_frontend *fe)
goto err;
}
err:
- if (!adap->suspend_resume_active)
- mutex_unlock(&adap->sync_mutex);
+ if (!adap->suspend_resume_active) {
+ clear_bit(ADAP_INIT, &adap->state_bits);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&adap->state_bits, ADAP_INIT);
+ }
dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
return ret;
@@ -534,8 +550,11 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
fe->id);
- if (!adap->suspend_resume_active)
- mutex_lock(&adap->sync_mutex);
+ if (!adap->suspend_resume_active) {
+ set_bit(ADAP_SLEEP, &adap->state_bits);
+ wait_on_bit(&adap->state_bits, ADAP_STREAMING, wait_schedule,
+ TASK_UNINTERRUPTIBLE);
+ }
if (adap->fe_sleep[fe->id]) {
ret = adap->fe_sleep[fe->id](fe);
@@ -555,7 +574,9 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
err:
if (!adap->suspend_resume_active) {
adap->active_fe = -1;
- mutex_unlock(&adap->sync_mutex);
+ clear_bit(ADAP_SLEEP, &adap->state_bits);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&adap->state_bits, ADAP_SLEEP);
}
dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
OpenPOWER on IntegriCloud