summaryrefslogtreecommitdiffstats
path: root/drivers/xen/mcelog.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/mcelog.c')
-rw-r--r--drivers/xen/mcelog.c18
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);