aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/common/siano
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-03-17 09:27:44 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-21 06:52:29 -0400
commit6a28bd94f4d068b6de65517e52f52b6840603d0a (patch)
treed67234d976b50a403ea5bcd93745ba4031c6417a /drivers/media/common/siano
parent773adad14135999380a4652b4ba01c5694827870 (diff)
[media] siano: add support for .poll on debugfs
Implement poll() method for debugfs and be sure that the debug_data won't be freed on ir or on read(). With this change, poll() will return POLLIN if either data was filled or if data was read. That allows read() to return 0 to indicate EOF in the latter case. As poll() is now provided, fix support for non-block mode. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common/siano')
-rw-r--r--drivers/media/common/siano/smsdvb-debugfs.c77
1 files changed, 59 insertions, 18 deletions
diff --git a/drivers/media/common/siano/smsdvb-debugfs.c b/drivers/media/common/siano/smsdvb-debugfs.c
index 59c7323f98d4..0219be36c289 100644
--- a/drivers/media/common/siano/smsdvb-debugfs.c
+++ b/drivers/media/common/siano/smsdvb-debugfs.c
@@ -352,6 +352,14 @@ static int smsdvb_stats_open(struct inode *inode, struct file *file)
352 return 0; 352 return 0;
353} 353}
354 354
355static void smsdvb_debugfs_data_release(struct kref *ref)
356{
357 struct smsdvb_debugfs *debug_data;
358
359 debug_data = container_of(ref, struct smsdvb_debugfs, refcount);
360 kfree(debug_data);
361}
362
355static int smsdvb_stats_wait_read(struct smsdvb_debugfs *debug_data) 363static int smsdvb_stats_wait_read(struct smsdvb_debugfs *debug_data)
356{ 364{
357 int rc = 1; 365 int rc = 1;
@@ -368,33 +376,65 @@ exit:
368 return rc; 376 return rc;
369} 377}
370 378
371static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf, 379static unsigned int smsdvb_stats_poll(struct file *file, poll_table *wait)
372 size_t nbytes, loff_t *ppos)
373{ 380{
374 int rc = 0;
375 struct smsdvb_debugfs *debug_data = file->private_data; 381 struct smsdvb_debugfs *debug_data = file->private_data;
382 int rc;
376 383
377 rc = wait_event_interruptible(debug_data->stats_queue, 384 kref_get(&debug_data->refcount);
378 smsdvb_stats_wait_read(debug_data));
379 if (rc < 0)
380 return rc;
381 385
382 rc = simple_read_from_buffer(user_buf, nbytes, ppos, 386 poll_wait(file, &debug_data->stats_queue, wait);
383 debug_data->stats_data, 387
384 debug_data->stats_count); 388 rc = smsdvb_stats_wait_read(debug_data);
385 spin_lock(&debug_data->lock); 389 if (rc > 0)
386 debug_data->stats_was_read = true; 390 rc = POLLIN | POLLRDNORM;
387 spin_unlock(&debug_data->lock); 391
392 kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
388 393
389 return rc; 394 return rc;
390} 395}
391 396
392static void smsdvb_debugfs_data_release(struct kref *ref) 397static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf,
398 size_t nbytes, loff_t *ppos)
393{ 399{
394 struct smsdvb_debugfs *debug_data; 400 int rc = 0, len;
401 struct smsdvb_debugfs *debug_data = file->private_data;
395 402
396 debug_data = container_of(ref, struct smsdvb_debugfs, refcount); 403 kref_get(&debug_data->refcount);
397 kfree(debug_data); 404
405 if (file->f_flags & O_NONBLOCK) {
406 rc = smsdvb_stats_wait_read(debug_data);
407 if (!rc) {
408 rc = -EWOULDBLOCK;
409 goto ret;
410 }
411 } else {
412 rc = wait_event_interruptible(debug_data->stats_queue,
413 smsdvb_stats_wait_read(debug_data));
414 if (rc < 0)
415 goto ret;
416 }
417
418 if (debug_data->stats_was_read) {
419 rc = 0; /* EOF */
420 goto ret;
421 }
422
423 len = debug_data->stats_count - *ppos;
424 if (len >= 0)
425 rc = simple_read_from_buffer(user_buf, nbytes, ppos,
426 debug_data->stats_data, len);
427 else
428 rc = 0;
429
430 if (*ppos >= debug_data->stats_count) {
431 spin_lock(&debug_data->lock);
432 debug_data->stats_was_read = true;
433 spin_unlock(&debug_data->lock);
434 }
435ret:
436 kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
437 return rc;
398} 438}
399 439
400static int smsdvb_stats_release(struct inode *inode, struct file *file) 440static int smsdvb_stats_release(struct inode *inode, struct file *file)
@@ -402,7 +442,7 @@ static int smsdvb_stats_release(struct inode *inode, struct file *file)
402 struct smsdvb_debugfs *debug_data = file->private_data; 442 struct smsdvb_debugfs *debug_data = file->private_data;
403 443
404 spin_lock(&debug_data->lock); 444 spin_lock(&debug_data->lock);
405 debug_data->stats_was_read = true; 445 debug_data->stats_was_read = true; /* return EOF to read() */
406 spin_unlock(&debug_data->lock); 446 spin_unlock(&debug_data->lock);
407 wake_up_interruptible_sync(&debug_data->stats_queue); 447 wake_up_interruptible_sync(&debug_data->stats_queue);
408 448
@@ -414,6 +454,7 @@ static int smsdvb_stats_release(struct inode *inode, struct file *file)
414 454
415static const struct file_operations debugfs_stats_ops = { 455static const struct file_operations debugfs_stats_ops = {
416 .open = smsdvb_stats_open, 456 .open = smsdvb_stats_open,
457 .poll = smsdvb_stats_poll,
417 .read = smsdvb_stats_read, 458 .read = smsdvb_stats_read,
418 .release = smsdvb_stats_release, 459 .release = smsdvb_stats_release,
419 .llseek = generic_file_llseek, 460 .llseek = generic_file_llseek,