#include <linux/debugfs.h>
 #include <linux/err.h>
+#include <linux/fs.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
        char                    *signal;
        char                    *message;
        spinlock_t              lock;
+       wait_queue_head_t       waitq;
+       struct fasync_struct    *async_queue;
 };
 
 static ssize_t mbox_test_signal_write(struct file *filp,
        .llseek = generic_file_llseek,
 };
 
+static int mbox_test_message_fasync(int fd, struct file *filp, int on)
+{
+       struct mbox_test_device *tdev = filp->private_data;
+
+       return fasync_helper(fd, filp, on, &tdev->async_queue);
+}
+
 static ssize_t mbox_test_message_write(struct file *filp,
                                       const char __user *userbuf,
                                       size_t count, loff_t *ppos)
        return ret < 0 ? ret : count;
 }
 
+static bool mbox_test_message_data_ready(struct mbox_test_device *tdev)
+{
+       unsigned char data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tdev->lock, flags);
+       data = tdev->rx_buffer[0];
+       spin_unlock_irqrestore(&tdev->lock, flags);
+
+       if (data != '\0')
+               return true;
+       return false;
+}
+
 static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
                                      size_t count, loff_t *ppos)
 {
        int l = 0;
        int ret;
 
+       DECLARE_WAITQUEUE(wait, current);
+
        touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL);
        if (!touser)
                return -ENOMEM;
                ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n");
                ret = simple_read_from_buffer(userbuf, count, ppos,
                                              touser, ret);
-               goto out;
+               goto kfree_err;
        }
 
-       if (tdev->rx_buffer[0] == '\0') {
-               ret = snprintf(touser, 9, "<EMPTY>\n");
-               ret = simple_read_from_buffer(userbuf, count, ppos,
-                                             touser, ret);
-               goto out;
-       }
+       add_wait_queue(&tdev->waitq, &wait);
+
+       do {
+               __set_current_state(TASK_INTERRUPTIBLE);
+
+               if (mbox_test_message_data_ready(tdev))
+                       break;
+
+               if (filp->f_flags & O_NONBLOCK) {
+                       ret = -EAGAIN;
+                       goto waitq_err;
+               }
+
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       goto waitq_err;
+               }
+               schedule();
+
+       } while (1);
 
        spin_lock_irqsave(&tdev->lock, flags);
 
        spin_unlock_irqrestore(&tdev->lock, flags);
 
        ret = simple_read_from_buffer(userbuf, count, ppos, touser, MBOX_HEXDUMP_MAX_LEN);
-out:
+waitq_err:
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&tdev->waitq, &wait);
+kfree_err:
        kfree(touser);
        return ret;
 }
 
+static unsigned int
+mbox_test_message_poll(struct file *filp, struct poll_table_struct *wait)
+{
+       struct mbox_test_device *tdev = filp->private_data;
+
+       poll_wait(filp, &tdev->waitq, wait);
+
+       if (mbox_test_message_data_ready(tdev))
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
 static const struct file_operations mbox_test_message_ops = {
        .write  = mbox_test_message_write,
        .read   = mbox_test_message_read,
+       .fasync = mbox_test_message_fasync,
+       .poll   = mbox_test_message_poll,
        .open   = simple_open,
        .llseek = generic_file_llseek,
 };
                memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN);
        }
        spin_unlock_irqrestore(&tdev->lock, flags);
+
+       wake_up_interruptible(&tdev->waitq);
+
+       kill_fasync(&tdev->async_queue, SIGIO, POLL_IN);
 }
 
 static void mbox_test_prepare_message(struct mbox_client *client, void *message)
        if (ret)
                return ret;
 
+       init_waitqueue_head(&tdev->waitq);
        dev_info(&pdev->dev, "Successfully registered\n");
 
        return 0;