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: Uma Krishnan <ukrishn@linux.vnet.ibm.com> Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Родитель
c207b57143
Коммит
bc65c1c7bf
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @afu: AFU associated with the host.
|
||||
|
@ -750,6 +852,8 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
|
|||
.release_context = ocxlflash_release_context,
|
||||
.perst_reloads_same_image = ocxlflash_perst_reloads_same_image,
|
||||
.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,
|
||||
.destroy_afu = ocxlflash_destroy_afu,
|
||||
.get_fd = ocxlflash_get_fd,
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
* 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 */
|
||||
struct ocxl_hw_afu {
|
||||
struct ocxlflash_context *ocxl_ctx; /* Host context */
|
||||
|
@ -45,4 +52,7 @@ struct ocxlflash_context {
|
|||
|
||||
phys_addr_t psn_phys; /* Process mapping */
|
||||
u64 psn_size; /* Process mapping size */
|
||||
|
||||
struct ocxlflash_irqs *irqs; /* Pointer to array of structures */
|
||||
int num_irqs; /* Number of interrupts */
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче