diff options
| -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); |
