summaryrefslogtreecommitdiffstats
path: root/drivers/xen/mcelog.c
diff options
context:
space:
mode:
authorLiu, Jinsong <jinsong.liu@intel.com>2012-06-15 03:03:39 +0200
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-07-19 21:51:41 +0200
commita867e5d6b362fc2982f19c5223f1946292643e57 (patch)
tree4dc03701387d766b5f2b44c3d3efa0e8e350f1b4 /drivers/xen/mcelog.c
parentxen/mce: schedule a workqueue to avoid sleep in atomic context (diff)
downloadlinux-a867e5d6b362fc2982f19c5223f1946292643e57.tar.xz
linux-a867e5d6b362fc2982f19c5223f1946292643e57.zip
xen/mce: add .poll method for mcelog device driver
If a driver leaves its poll method NULL, the device is assumed to be both readable and writable without blocking. This patch add .poll method to xen mcelog device driver, so that when mcelog use system calls like ppoll or select, it would be blocked when no data available, and avoid spinning at CPU. Reported-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
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 804aa3c181c2..8feee08bcb43 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);