diff options
Diffstat (limited to 'drivers/xen/mcelog.c')
-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 804aa3c181c2..8feee08bcb43 100644 --- a/drivers/xen/mcelog.c +++ b/drivers/xen/mcelog.c | |||
@@ -41,6 +41,8 @@ | |||
41 | #include <linux/miscdevice.h> | 41 | #include <linux/miscdevice.h> |
42 | #include <linux/uaccess.h> | 42 | #include <linux/uaccess.h> |
43 | #include <linux/capability.h> | 43 | #include <linux/capability.h> |
44 | #include <linux/poll.h> | ||
45 | #include <linux/sched.h> | ||
44 | 46 | ||
45 | #include <xen/interface/xen.h> | 47 | #include <xen/interface/xen.h> |
46 | #include <xen/events.h> | 48 | #include <xen/events.h> |
@@ -67,6 +69,8 @@ static DEFINE_SPINLOCK(xen_mce_chrdev_state_lock); | |||
67 | static int xen_mce_chrdev_open_count; /* #times opened */ | 69 | static int xen_mce_chrdev_open_count; /* #times opened */ |
68 | static int xen_mce_chrdev_open_exclu; /* already open exclusive? */ | 70 | static int xen_mce_chrdev_open_exclu; /* already open exclusive? */ |
69 | 71 | ||
72 | static DECLARE_WAIT_QUEUE_HEAD(xen_mce_chrdev_wait); | ||
73 | |||
70 | static int xen_mce_chrdev_open(struct inode *inode, struct file *file) | 74 | static int xen_mce_chrdev_open(struct inode *inode, struct file *file) |
71 | { | 75 | { |
72 | spin_lock(&xen_mce_chrdev_state_lock); | 76 | spin_lock(&xen_mce_chrdev_state_lock); |
@@ -135,6 +139,16 @@ out: | |||
135 | return err ? err : buf - ubuf; | 139 | return err ? err : buf - ubuf; |
136 | } | 140 | } |
137 | 141 | ||
142 | static unsigned int xen_mce_chrdev_poll(struct file *file, poll_table *wait) | ||
143 | { | ||
144 | poll_wait(file, &xen_mce_chrdev_wait, wait); | ||
145 | |||
146 | if (xen_mcelog.next) | ||
147 | return POLLIN | POLLRDNORM; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
138 | static long xen_mce_chrdev_ioctl(struct file *f, unsigned int cmd, | 152 | static long xen_mce_chrdev_ioctl(struct file *f, unsigned int cmd, |
139 | unsigned long arg) | 153 | unsigned long arg) |
140 | { | 154 | { |
@@ -166,6 +180,7 @@ static const struct file_operations xen_mce_chrdev_ops = { | |||
166 | .open = xen_mce_chrdev_open, | 180 | .open = xen_mce_chrdev_open, |
167 | .release = xen_mce_chrdev_release, | 181 | .release = xen_mce_chrdev_release, |
168 | .read = xen_mce_chrdev_read, | 182 | .read = xen_mce_chrdev_read, |
183 | .poll = xen_mce_chrdev_poll, | ||
169 | .unlocked_ioctl = xen_mce_chrdev_ioctl, | 184 | .unlocked_ioctl = xen_mce_chrdev_ioctl, |
170 | .llseek = no_llseek, | 185 | .llseek = no_llseek, |
171 | }; | 186 | }; |
@@ -329,6 +344,9 @@ static void xen_mce_work_fn(struct work_struct *work) | |||
329 | pr_err(XEN_MCELOG | 344 | pr_err(XEN_MCELOG |
330 | "Failed to handle nonurgent mc_info queue.\n"); | 345 | "Failed to handle nonurgent mc_info queue.\n"); |
331 | 346 | ||
347 | /* wake processes polling /dev/mcelog */ | ||
348 | wake_up_interruptible(&xen_mce_chrdev_wait); | ||
349 | |||
332 | mutex_unlock(&mcelog_lock); | 350 | mutex_unlock(&mcelog_lock); |
333 | } | 351 | } |
334 | static DECLARE_WORK(xen_mce_work, xen_mce_work_fn); | 352 | static DECLARE_WORK(xen_mce_work, xen_mce_work_fn); |