diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/xen/mcelog.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/xen/mcelog.c b/drivers/xen/mcelog.c index 804aa3c181c..8feee08bcb4 100644 --- a/drivers/xen/mcelog.c +++ b/drivers/xen/mcelog.c @@ -41,6 +41,8 @@ #include <linux/miscdevice.h> #include <linux/uaccess.h> #include <linux/capability.h> +#include <linux/poll.h> +#include <linux/sched.h> #include <xen/interface/xen.h> #include <xen/events.h> @@ -67,6 +69,8 @@ static DEFINE_SPINLOCK(xen_mce_chrdev_state_lock); static int xen_mce_chrdev_open_count; /* #times opened */ static int xen_mce_chrdev_open_exclu; /* already open exclusive? */ +static DECLARE_WAIT_QUEUE_HEAD(xen_mce_chrdev_wait); + static int xen_mce_chrdev_open(struct inode *inode, struct file *file) { spin_lock(&xen_mce_chrdev_state_lock); @@ -135,6 +139,16 @@ out: return err ? err : buf - ubuf; } +static unsigned int xen_mce_chrdev_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &xen_mce_chrdev_wait, wait); + + if (xen_mcelog.next) + return POLLIN | POLLRDNORM; + + return 0; +} + static long xen_mce_chrdev_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { @@ -166,6 +180,7 @@ static const struct file_operations xen_mce_chrdev_ops = { .open = xen_mce_chrdev_open, .release = xen_mce_chrdev_release, .read = xen_mce_chrdev_read, + .poll = xen_mce_chrdev_poll, .unlocked_ioctl = xen_mce_chrdev_ioctl, .llseek = no_llseek, }; @@ -329,6 +344,9 @@ static void xen_mce_work_fn(struct work_struct *work) pr_err(XEN_MCELOG "Failed to handle nonurgent mc_info queue.\n"); + /* wake processes polling /dev/mcelog */ + wake_up_interruptible(&xen_mce_chrdev_wait); + mutex_unlock(&mcelog_lock); } static DECLARE_WORK(xen_mce_work, xen_mce_work_fn); |