Commit 56f1db1a authored by Uma Krishnan's avatar Uma Krishnan Committed by Martin K. Petersen

scsi: cxlflash: Support adapter context polling

The cxlflash userspace API requires that users be able to poll the adapter
context for any pending events or interrupts from the AFU. Support polling on
various events by implementing the AFU poll fop using a waitqueue.
Signed-off-by: default avatarUma Krishnan <ukrishn@linux.vnet.ibm.com>
Acked-by: default avatarMatthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 762c7e93
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/poll.h>
#include <misc/ocxl.h> #include <misc/ocxl.h>
...@@ -452,6 +453,7 @@ static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie) ...@@ -452,6 +453,7 @@ static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
} }
spin_lock_init(&ctx->slock); spin_lock_init(&ctx->slock);
init_waitqueue_head(&ctx->wq);
ctx->pe = rc; ctx->pe = rc;
ctx->master = false; ctx->master = false;
...@@ -892,10 +894,57 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev) ...@@ -892,10 +894,57 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
goto out; 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 = { static const struct file_operations ocxl_afu_fops = {
.owner = THIS_MODULE, .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 * ocxlflash_get_fd() - get file descriptor for an adapter context
* @ctx_cookie: Adapter context. * @ctx_cookie: Adapter context.
...@@ -933,8 +982,10 @@ static struct file *ocxlflash_get_fd(void *ctx_cookie, ...@@ -933,8 +982,10 @@ static struct file *ocxlflash_get_fd(void *ctx_cookie,
} }
fdtmp = rc; fdtmp = rc;
/* Use default ops if there is no fops */ /* Patch the file ops that are not defined */
if (!fops) if (fops) {
PATCH_FOPS(poll);
} else /* Use default ops */
fops = (struct file_operations *)&ocxl_afu_fops; fops = (struct file_operations *)&ocxl_afu_fops;
name = kasprintf(GFP_KERNEL, "ocxlflash:%d", ctx->pe); name = kasprintf(GFP_KERNEL, "ocxlflash:%d", ctx->pe);
...@@ -998,6 +1049,8 @@ static irqreturn_t ocxlflash_afu_irq(int irq, void *data) ...@@ -998,6 +1049,8 @@ static irqreturn_t ocxlflash_afu_irq(int irq, void *data)
set_bit(i - 1, &ctx->irq_bitmap); set_bit(i - 1, &ctx->irq_bitmap);
ctx->pending_irq = true; ctx->pending_irq = true;
spin_unlock(&ctx->slock); spin_unlock(&ctx->slock);
wake_up_all(&ctx->wq);
out: out:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -56,6 +56,8 @@ struct ocxlflash_context { ...@@ -56,6 +56,8 @@ struct ocxlflash_context {
u64 psn_size; /* Process mapping size */ u64 psn_size; /* Process mapping size */
spinlock_t slock; /* Protects irq/fault/event updates */ spinlock_t slock; /* Protects irq/fault/event updates */
wait_queue_head_t wq; /* Wait queue for poll and interrupts */
struct ocxlflash_irqs *irqs; /* Pointer to array of structures */ struct ocxlflash_irqs *irqs; /* Pointer to array of structures */
int num_irqs; /* Number of interrupts */ int num_irqs; /* Number of interrupts */
bool pending_irq; /* Pending interrupt on the context */ bool pending_irq; /* Pending interrupt on the context */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment