scsi: cxlflash: Adapter context support for OCXL
Add support to create and release the adapter contexts for OCXL and provide means to specify certain contexts as a master. The existing cxlflash core has a design requirement that each host will have a single host context available by default. To satisfy this requirement, one host adapter context is created when the hardware AFU is initialized. This is returned by the get_context() fop. Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com> Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Reviewed-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Родитель
41df40d817
Коммит
f6b4557c98
|
@ -17,6 +17,80 @@
|
|||
#include "backend.h"
|
||||
#include "ocxl_hw.h"
|
||||
|
||||
/**
|
||||
* ocxlflash_set_master() - sets the context as master
|
||||
* @ctx_cookie: Adapter context to set as master.
|
||||
*/
|
||||
static void ocxlflash_set_master(void *ctx_cookie)
|
||||
{
|
||||
struct ocxlflash_context *ctx = ctx_cookie;
|
||||
|
||||
ctx->master = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocxlflash_get_context() - obtains the context associated with the host
|
||||
* @pdev: PCI device associated with the host.
|
||||
* @afu_cookie: Hardware AFU associated with the host.
|
||||
*
|
||||
* Return: returns the pointer to host adapter context
|
||||
*/
|
||||
static void *ocxlflash_get_context(struct pci_dev *pdev, void *afu_cookie)
|
||||
{
|
||||
struct ocxl_hw_afu *afu = afu_cookie;
|
||||
|
||||
return afu->ocxl_ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocxlflash_dev_context_init() - allocate and initialize an adapter context
|
||||
* @pdev: PCI device associated with the host.
|
||||
* @afu_cookie: Hardware AFU associated with the host.
|
||||
*
|
||||
* Return: returns the adapter context on success, ERR_PTR on failure
|
||||
*/
|
||||
static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
|
||||
{
|
||||
struct ocxl_hw_afu *afu = afu_cookie;
|
||||
struct device *dev = afu->dev;
|
||||
struct ocxlflash_context *ctx;
|
||||
int rc;
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (unlikely(!ctx)) {
|
||||
dev_err(dev, "%s: Context allocation failed\n", __func__);
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx->master = false;
|
||||
ctx->hw_afu = afu;
|
||||
out:
|
||||
return ctx;
|
||||
err:
|
||||
ctx = ERR_PTR(rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocxlflash_release_context() - releases an adapter context
|
||||
* @ctx_cookie: Adapter context to be released.
|
||||
*
|
||||
* Return: 0 on success, -errno on failure
|
||||
*/
|
||||
static int ocxlflash_release_context(void *ctx_cookie)
|
||||
{
|
||||
struct ocxlflash_context *ctx = ctx_cookie;
|
||||
int rc = 0;
|
||||
|
||||
if (!ctx)
|
||||
goto out;
|
||||
|
||||
kfree(ctx);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocxlflash_destroy_afu() - destroy the AFU structure
|
||||
* @afu_cookie: AFU to be freed.
|
||||
|
@ -28,6 +102,7 @@ static void ocxlflash_destroy_afu(void *afu_cookie)
|
|||
if (!afu)
|
||||
return;
|
||||
|
||||
ocxlflash_release_context(afu->ocxl_ctx);
|
||||
kfree(afu);
|
||||
}
|
||||
|
||||
|
@ -134,6 +209,7 @@ out:
|
|||
static void *ocxlflash_create_afu(struct pci_dev *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ocxlflash_context *ctx;
|
||||
struct ocxl_hw_afu *afu;
|
||||
int rc;
|
||||
|
||||
|
@ -159,6 +235,16 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
|
|||
__func__, rc);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
ctx = ocxlflash_dev_context_init(pdev, afu);
|
||||
if (IS_ERR(ctx)) {
|
||||
rc = PTR_ERR(ctx);
|
||||
dev_err(dev, "%s: ocxlflash_dev_context_init failed rc=%d\n",
|
||||
__func__, rc);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
afu->ocxl_ctx = ctx;
|
||||
out:
|
||||
return afu;
|
||||
err1:
|
||||
|
@ -170,6 +256,10 @@ err1:
|
|||
/* Backend ops to ocxlflash services */
|
||||
const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
|
||||
.module = THIS_MODULE,
|
||||
.set_master = ocxlflash_set_master,
|
||||
.get_context = ocxlflash_get_context,
|
||||
.dev_context_init = ocxlflash_dev_context_init,
|
||||
.release_context = ocxlflash_release_context,
|
||||
.create_afu = ocxlflash_create_afu,
|
||||
.destroy_afu = ocxlflash_destroy_afu,
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
/* OCXL hardware AFU associated with the host */
|
||||
struct ocxl_hw_afu {
|
||||
struct ocxlflash_context *ocxl_ctx; /* Host context */
|
||||
struct pci_dev *pdev; /* PCI device */
|
||||
struct device *dev; /* Generic device */
|
||||
|
||||
|
@ -28,3 +29,8 @@ struct ocxl_hw_afu {
|
|||
int max_pasid; /* Maximum number of contexts */
|
||||
bool is_present; /* Function has AFUs defined */
|
||||
};
|
||||
|
||||
struct ocxlflash_context {
|
||||
struct ocxl_hw_afu *hw_afu; /* HW AFU back pointer */
|
||||
bool master; /* Whether this is a master context */
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче