aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@s-opensource.com>2018-02-09 10:44:49 -0500
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2018-02-23 05:27:10 -0500
commit0b23498aacc658e4d0f6b240f0b905908695a132 (patch)
tree29934a00c2b1c94786bcfb71a13d94a42dc3c8d0
parenta145f64c6107d3aa5a7cec9f8977d04ac2a896c9 (diff)
media: dmxdev: Fix the logic that enables DMA mmap support
Some conditions required for DVB mmap support to work are reversed. Also, the logic is not too clear. So, improve the logic, making it easier to be handled. PS.: I'm pretty sure that I fixed it while testing, but, somehow, the change got lost. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r--drivers/media/dvb-core/dmxdev.c75
-rw-r--r--include/media/dmxdev.h2
2 files changed, 44 insertions, 33 deletions
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index d87b69b86a59..09c2626b5bf9 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -128,11 +128,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
128 struct dvb_device *dvbdev = file->private_data; 128 struct dvb_device *dvbdev = file->private_data;
129 struct dmxdev *dmxdev = dvbdev->priv; 129 struct dmxdev *dmxdev = dvbdev->priv;
130 struct dmx_frontend *front; 130 struct dmx_frontend *front;
131#ifndef CONFIG_DVB_MMAP
132 bool need_ringbuffer = false; 131 bool need_ringbuffer = false;
133#else
134 const bool need_ringbuffer = true;
135#endif
136 132
137 dprintk("%s\n", __func__); 133 dprintk("%s\n", __func__);
138 134
@@ -144,17 +140,31 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
144 return -ENODEV; 140 return -ENODEV;
145 } 141 }
146 142
147#ifndef CONFIG_DVB_MMAP 143 dmxdev->may_do_mmap = 0;
144
145 /*
146 * The logic here is a little tricky due to the ifdef.
147 *
148 * The ringbuffer is used for both read and mmap.
149 *
150 * It is not needed, however, on two situations:
151 * - Write devices (access with O_WRONLY);
152 * - For duplex device nodes, opened with O_RDWR.
153 */
154
148 if ((file->f_flags & O_ACCMODE) == O_RDONLY) 155 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
149 need_ringbuffer = true; 156 need_ringbuffer = true;
150#else 157 else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
151 if ((file->f_flags & O_ACCMODE) == O_RDWR) {
152 if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { 158 if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
159#ifdef CONFIG_DVB_MMAP
160 dmxdev->may_do_mmap = 1;
161 need_ringbuffer = true;
162#else
153 mutex_unlock(&dmxdev->mutex); 163 mutex_unlock(&dmxdev->mutex);
154 return -EOPNOTSUPP; 164 return -EOPNOTSUPP;
165#endif
155 } 166 }
156 } 167 }
157#endif
158 168
159 if (need_ringbuffer) { 169 if (need_ringbuffer) {
160 void *mem; 170 void *mem;
@@ -169,8 +179,9 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
169 return -ENOMEM; 179 return -ENOMEM;
170 } 180 }
171 dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); 181 dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
172 dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr", 182 if (dmxdev->may_do_mmap)
173 file->f_flags & O_NONBLOCK); 183 dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
184 file->f_flags & O_NONBLOCK);
174 dvbdev->readers--; 185 dvbdev->readers--;
175 } 186 }
176 187
@@ -200,11 +211,6 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
200{ 211{
201 struct dvb_device *dvbdev = file->private_data; 212 struct dvb_device *dvbdev = file->private_data;
202 struct dmxdev *dmxdev = dvbdev->priv; 213 struct dmxdev *dmxdev = dvbdev->priv;
203#ifndef CONFIG_DVB_MMAP
204 bool need_ringbuffer = false;
205#else
206 const bool need_ringbuffer = true;
207#endif
208 214
209 mutex_lock(&dmxdev->mutex); 215 mutex_lock(&dmxdev->mutex);
210 216
@@ -213,15 +219,14 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
213 dmxdev->demux->connect_frontend(dmxdev->demux, 219 dmxdev->demux->connect_frontend(dmxdev->demux,
214 dmxdev->dvr_orig_fe); 220 dmxdev->dvr_orig_fe);
215 } 221 }
216#ifndef CONFIG_DVB_MMAP
217 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
218 need_ringbuffer = true;
219#endif
220 222
221 if (need_ringbuffer) { 223 if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
222 if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx)) 224 dmxdev->may_do_mmap) {
223 dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx); 225 if (dmxdev->may_do_mmap) {
224 dvb_vb2_release(&dmxdev->dvr_vb2_ctx); 226 if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
227 dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
228 dvb_vb2_release(&dmxdev->dvr_vb2_ctx);
229 }
225 dvbdev->readers++; 230 dvbdev->readers++;
226 if (dmxdev->dvr_buffer.data) { 231 if (dmxdev->dvr_buffer.data) {
227 void *mem = dmxdev->dvr_buffer.data; 232 void *mem = dmxdev->dvr_buffer.data;
@@ -802,6 +807,12 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
802 mutex_init(&dmxdevfilter->mutex); 807 mutex_init(&dmxdevfilter->mutex);
803 file->private_data = dmxdevfilter; 808 file->private_data = dmxdevfilter;
804 809
810#ifdef CONFIG_DVB_MMAP
811 dmxdev->may_do_mmap = 1;
812#else
813 dmxdev->may_do_mmap = 0;
814#endif
815
805 dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); 816 dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
806 dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter", 817 dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter",
807 file->f_flags & O_NONBLOCK); 818 file->f_flags & O_NONBLOCK);
@@ -1206,6 +1217,9 @@ static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
1206 struct dmxdev *dmxdev = dmxdevfilter->dev; 1217 struct dmxdev *dmxdev = dmxdevfilter->dev;
1207 int ret; 1218 int ret;
1208 1219
1220 if (!dmxdev->may_do_mmap)
1221 return -EOPNOTSUPP;
1222
1209 if (mutex_lock_interruptible(&dmxdev->mutex)) 1223 if (mutex_lock_interruptible(&dmxdev->mutex))
1210 return -ERESTARTSYS; 1224 return -ERESTARTSYS;
1211 1225
@@ -1322,11 +1336,6 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
1322 struct dvb_device *dvbdev = file->private_data; 1336 struct dvb_device *dvbdev = file->private_data;
1323 struct dmxdev *dmxdev = dvbdev->priv; 1337 struct dmxdev *dmxdev = dvbdev->priv;
1324 __poll_t mask = 0; 1338 __poll_t mask = 0;
1325#ifndef CONFIG_DVB_MMAP
1326 bool need_ringbuffer = false;
1327#else
1328 const bool need_ringbuffer = true;
1329#endif
1330 1339
1331 dprintk("%s\n", __func__); 1340 dprintk("%s\n", __func__);
1332 1341
@@ -1337,11 +1346,8 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
1337 1346
1338 poll_wait(file, &dmxdev->dvr_buffer.queue, wait); 1347 poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
1339 1348
1340#ifndef CONFIG_DVB_MMAP 1349 if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
1341 if ((file->f_flags & O_ACCMODE) == O_RDONLY) 1350 dmxdev->may_do_mmap) {
1342 need_ringbuffer = true;
1343#endif
1344 if (need_ringbuffer) {
1345 if (dmxdev->dvr_buffer.error) 1351 if (dmxdev->dvr_buffer.error)
1346 mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR); 1352 mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
1347 1353
@@ -1360,6 +1366,9 @@ static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
1360 struct dmxdev *dmxdev = dvbdev->priv; 1366 struct dmxdev *dmxdev = dvbdev->priv;
1361 int ret; 1367 int ret;
1362 1368
1369 if (!dmxdev->may_do_mmap)
1370 return -EOPNOTSUPP;
1371
1363 if (dmxdev->exit) 1372 if (dmxdev->exit)
1364 return -ENODEV; 1373 return -ENODEV;
1365 1374
diff --git a/include/media/dmxdev.h b/include/media/dmxdev.h
index 2f5cb2c7b6a7..baafa3b8aca4 100644
--- a/include/media/dmxdev.h
+++ b/include/media/dmxdev.h
@@ -163,6 +163,7 @@ struct dmxdev_filter {
163 * @demux: pointer to &struct dmx_demux. 163 * @demux: pointer to &struct dmx_demux.
164 * @filternum: number of filters. 164 * @filternum: number of filters.
165 * @capabilities: demux capabilities as defined by &enum dmx_demux_caps. 165 * @capabilities: demux capabilities as defined by &enum dmx_demux_caps.
166 * @may_do_mmap: flag used to indicate if the device may do mmap.
166 * @exit: flag to indicate that the demux is being released. 167 * @exit: flag to indicate that the demux is being released.
167 * @dvr_orig_fe: pointer to &struct dmx_frontend. 168 * @dvr_orig_fe: pointer to &struct dmx_frontend.
168 * @dvr_buffer: embedded &struct dvb_ringbuffer for DVB output. 169 * @dvr_buffer: embedded &struct dvb_ringbuffer for DVB output.
@@ -180,6 +181,7 @@ struct dmxdev {
180 int filternum; 181 int filternum;
181 int capabilities; 182 int capabilities;
182 183
184 unsigned int may_do_mmap:1;
183 unsigned int exit:1; 185 unsigned int exit:1;
184#define DMXDEV_CAP_DUPLEX 1 186#define DMXDEV_CAP_DUPLEX 1
185 struct dmx_frontend *dvr_orig_fe; 187 struct dmx_frontend *dvr_orig_fe;