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

scsi: cxlflash: Support AFU interrupt management

Add support to allocate and free AFU interrupts using the OCXL provider
services. The trigger page returned upon successful allocation will be mapped
and exposed to the cxlflash core in a future commit.
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 c207b571
...@@ -384,6 +384,108 @@ static ssize_t ocxlflash_read_adapter_vpd(struct pci_dev *pdev, void *buf, ...@@ -384,6 +384,108 @@ static ssize_t ocxlflash_read_adapter_vpd(struct pci_dev *pdev, void *buf,
return pci_read_vpd(pdev, 0, count, buf); return pci_read_vpd(pdev, 0, count, buf);
} }
/**
* free_afu_irqs() - internal service to free interrupts
* @ctx: Adapter context.
*/
static void free_afu_irqs(struct ocxlflash_context *ctx)
{
struct ocxl_hw_afu *afu = ctx->hw_afu;
struct device *dev = afu->dev;
int i;
if (!ctx->irqs) {
dev_err(dev, "%s: Interrupts not allocated\n", __func__);
return;
}
for (i = ctx->num_irqs; i >= 0; i--)
ocxl_link_free_irq(afu->link_token, ctx->irqs[i].hwirq);
kfree(ctx->irqs);
ctx->irqs = NULL;
}
/**
* alloc_afu_irqs() - internal service to allocate interrupts
* @ctx: Context associated with the request.
* @num: Number of interrupts requested.
*
* Return: 0 on success, -errno on failure
*/
static int alloc_afu_irqs(struct ocxlflash_context *ctx, int num)
{
struct ocxl_hw_afu *afu = ctx->hw_afu;
struct device *dev = afu->dev;
struct ocxlflash_irqs *irqs;
u64 addr;
int rc = 0;
int hwirq;
int i;
if (ctx->irqs) {
dev_err(dev, "%s: Interrupts already allocated\n", __func__);
rc = -EEXIST;
goto out;
}
if (num > OCXL_MAX_IRQS) {
dev_err(dev, "%s: Too many interrupts num=%d\n", __func__, num);
rc = -EINVAL;
goto out;
}
irqs = kcalloc(num, sizeof(*irqs), GFP_KERNEL);
if (unlikely(!irqs)) {
dev_err(dev, "%s: Context irqs allocation failed\n", __func__);
rc = -ENOMEM;
goto out;
}
for (i = 0; i < num; i++) {
rc = ocxl_link_irq_alloc(afu->link_token, &hwirq, &addr);
if (unlikely(rc)) {
dev_err(dev, "%s: ocxl_link_irq_alloc failed rc=%d\n",
__func__, rc);
goto err;
}
irqs[i].hwirq = hwirq;
irqs[i].ptrig = addr;
}
ctx->irqs = irqs;
ctx->num_irqs = num;
out:
return rc;
err:
for (i = i-1; i >= 0; i--)
ocxl_link_free_irq(afu->link_token, irqs[i].hwirq);
kfree(irqs);
goto out;
}
/**
* ocxlflash_allocate_afu_irqs() - allocates the requested number of interrupts
* @ctx_cookie: Context associated with the request.
* @num: Number of interrupts requested.
*
* Return: 0 on success, -errno on failure
*/
static int ocxlflash_allocate_afu_irqs(void *ctx_cookie, int num)
{
return alloc_afu_irqs(ctx_cookie, num);
}
/**
* ocxlflash_free_afu_irqs() - frees the interrupts of an adapter context
* @ctx_cookie: Adapter context.
*/
static void ocxlflash_free_afu_irqs(void *ctx_cookie)
{
free_afu_irqs(ctx_cookie);
}
/** /**
* ocxlflash_unconfig_afu() - unconfigure the AFU * ocxlflash_unconfig_afu() - unconfigure the AFU
* @afu: AFU associated with the host. * @afu: AFU associated with the host.
...@@ -750,6 +852,8 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = { ...@@ -750,6 +852,8 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.release_context = ocxlflash_release_context, .release_context = ocxlflash_release_context,
.perst_reloads_same_image = ocxlflash_perst_reloads_same_image, .perst_reloads_same_image = ocxlflash_perst_reloads_same_image,
.read_adapter_vpd = ocxlflash_read_adapter_vpd, .read_adapter_vpd = ocxlflash_read_adapter_vpd,
.allocate_afu_irqs = ocxlflash_allocate_afu_irqs,
.free_afu_irqs = ocxlflash_free_afu_irqs,
.create_afu = ocxlflash_create_afu, .create_afu = ocxlflash_create_afu,
.destroy_afu = ocxlflash_destroy_afu, .destroy_afu = ocxlflash_destroy_afu,
.get_fd = ocxlflash_get_fd, .get_fd = ocxlflash_get_fd,
......
...@@ -12,6 +12,13 @@ ...@@ -12,6 +12,13 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#define OCXL_MAX_IRQS 4 /* Max interrupts per process */
struct ocxlflash_irqs {
int hwirq;
u64 ptrig;
};
/* OCXL hardware AFU associated with the host */ /* OCXL hardware AFU associated with the host */
struct ocxl_hw_afu { struct ocxl_hw_afu {
struct ocxlflash_context *ocxl_ctx; /* Host context */ struct ocxlflash_context *ocxl_ctx; /* Host context */
...@@ -45,4 +52,7 @@ struct ocxlflash_context { ...@@ -45,4 +52,7 @@ struct ocxlflash_context {
phys_addr_t psn_phys; /* Process mapping */ phys_addr_t psn_phys; /* Process mapping */
u64 psn_size; /* Process mapping size */ u64 psn_size; /* Process mapping size */
struct ocxlflash_irqs *irqs; /* Pointer to array of structures */
int num_irqs; /* Number of interrupts */
}; };
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