return 0;
 }
 
+static void smsdvb_debugfs_data_release(struct kref *ref)
+{
+       struct smsdvb_debugfs *debug_data;
+
+       debug_data = container_of(ref, struct smsdvb_debugfs, refcount);
+       kfree(debug_data);
+}
+
 static int smsdvb_stats_wait_read(struct smsdvb_debugfs *debug_data)
 {
        int rc = 1;
        return rc;
 }
 
-static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf,
-                                     size_t nbytes, loff_t *ppos)
+static unsigned int smsdvb_stats_poll(struct file *file, poll_table *wait)
 {
-       int rc = 0;
        struct smsdvb_debugfs *debug_data = file->private_data;
+       int rc;
 
-       rc = wait_event_interruptible(debug_data->stats_queue,
-                                     smsdvb_stats_wait_read(debug_data));
-       if (rc < 0)
-               return rc;
+       kref_get(&debug_data->refcount);
 
-       rc = simple_read_from_buffer(user_buf, nbytes, ppos,
-                                    debug_data->stats_data,
-                                    debug_data->stats_count);
-       spin_lock(&debug_data->lock);
-       debug_data->stats_was_read = true;
-       spin_unlock(&debug_data->lock);
+       poll_wait(file, &debug_data->stats_queue, wait);
+
+       rc = smsdvb_stats_wait_read(debug_data);
+       if (rc > 0)
+               rc = POLLIN | POLLRDNORM;
+
+       kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
 
        return rc;
 }
 
-static void smsdvb_debugfs_data_release(struct kref *ref)
+static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf,
+                                     size_t nbytes, loff_t *ppos)
 {
-       struct smsdvb_debugfs *debug_data;
+       int rc = 0, len;
+       struct smsdvb_debugfs *debug_data = file->private_data;
 
-       debug_data = container_of(ref, struct smsdvb_debugfs, refcount);
-       kfree(debug_data);
+       kref_get(&debug_data->refcount);
+
+       if (file->f_flags & O_NONBLOCK) {
+               rc = smsdvb_stats_wait_read(debug_data);
+               if (!rc) {
+                       rc = -EWOULDBLOCK;
+                       goto ret;
+               }
+       } else {
+               rc = wait_event_interruptible(debug_data->stats_queue,
+                                     smsdvb_stats_wait_read(debug_data));
+               if (rc < 0)
+                       goto ret;
+       }
+
+       if (debug_data->stats_was_read) {
+               rc = 0; /* EOF */
+               goto ret;
+       }
+
+       len = debug_data->stats_count - *ppos;
+       if (len >= 0)
+               rc = simple_read_from_buffer(user_buf, nbytes, ppos,
+                                            debug_data->stats_data, len);
+       else
+               rc = 0;
+
+       if (*ppos >= debug_data->stats_count) {
+               spin_lock(&debug_data->lock);
+               debug_data->stats_was_read = true;
+               spin_unlock(&debug_data->lock);
+       }
+ret:
+       kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
+       return rc;
 }
 
 static int smsdvb_stats_release(struct inode *inode, struct file *file)
        struct smsdvb_debugfs *debug_data = file->private_data;
 
        spin_lock(&debug_data->lock);
-       debug_data->stats_was_read = true;
+       debug_data->stats_was_read = true;      /* return EOF to read() */
        spin_unlock(&debug_data->lock);
        wake_up_interruptible_sync(&debug_data->stats_queue);
 
 
 static const struct file_operations debugfs_stats_ops = {
        .open = smsdvb_stats_open,
+       .poll = smsdvb_stats_poll,
        .read = smsdvb_stats_read,
        .release = smsdvb_stats_release,
        .llseek = generic_file_llseek,