#include <linux/idr.h>
#include <linux/module.h>
#include <linux/mount.h>
+#include <linux/poll.h>
#include <misc/ocxl.h>
}
spin_lock_init(&ctx->slock);
+ init_waitqueue_head(&ctx->wq);
ctx->pe = rc;
ctx->master = false;
goto out;
}
+/**
+ * ctx_event_pending() - check for any event pending on the context
+ * @ctx: Context to be checked.
+ *
+ * Return: true if there is an event pending, false if none pending
+ */
+static inline bool ctx_event_pending(struct ocxlflash_context *ctx)
+{
+ if (ctx->pending_irq)
+ return true;
+
+ return false;
+}
+
+/**
+ * afu_poll() - poll the AFU for events on the context
+ * @file: File associated with the adapter context.
+ * @poll: Poll structure from the user.
+ *
+ * Return: poll mask
+ */
+static unsigned int afu_poll(struct file *file, struct poll_table_struct *poll)
+{
+ struct ocxlflash_context *ctx = file->private_data;
+ struct device *dev = ctx->hw_afu->dev;
+ ulong lock_flags;
+ int mask = 0;
+
+ poll_wait(file, &ctx->wq, poll);
+
+ spin_lock_irqsave(&ctx->slock, lock_flags);
+ if (ctx_event_pending(ctx))
+ mask |= POLLIN | POLLRDNORM;
+ else
+ mask |= POLLERR;
+ spin_unlock_irqrestore(&ctx->slock, lock_flags);
+
+ dev_dbg(dev, "%s: Poll wait completed for pe %i mask %i\n",
+ __func__, ctx->pe, mask);
+
+ return mask;
+}
+
static const struct file_operations ocxl_afu_fops = {
.owner = THIS_MODULE,
+ .poll = afu_poll,
};
+#define PATCH_FOPS(NAME) \
+ do { if (!fops->NAME) fops->NAME = ocxl_afu_fops.NAME; } while (0)
+
/**
* ocxlflash_get_fd() - get file descriptor for an adapter context
* @ctx_cookie: Adapter context.
}
fdtmp = rc;
- /* Use default ops if there is no fops */
- if (!fops)
+ /* Patch the file ops that are not defined */
+ if (fops) {
+ PATCH_FOPS(poll);
+ } else /* Use default ops */
fops = (struct file_operations *)&ocxl_afu_fops;
name = kasprintf(GFP_KERNEL, "ocxlflash:%d", ctx->pe);
set_bit(i - 1, &ctx->irq_bitmap);
ctx->pending_irq = true;
spin_unlock(&ctx->slock);
+
+ wake_up_all(&ctx->wq);
out:
return IRQ_HANDLED;
}