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

scsi: cxlflash: Read host function configuration

Per the OCXL specification, the underlying host can have multiple AFUs per
function with each function supporting its own configuration. The host
function configuration is read on the initialization path to evaluate the
number of functions present and identify the features and configuration of the
functions present. This data is cached for use in later configuration
steps. Note that for the OCXL hardware supported by the cxlflash driver, only
one AFU per function is expected.
Signed-off-by: default avatarUma Krishnan <ukrishn@linux.vnet.ibm.com>
Acked-by: default avatarMatthew R. Ochs <mrochs@linux.vnet.ibm.com>
Reviewed-by: default avatarAndrew Donnellan <andrew.donnellan@au1.ibm.com>
Reviewed-by: default avatarFrederic Barrat <fbarrat@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 48e077db
...@@ -31,6 +31,38 @@ static void ocxlflash_destroy_afu(void *afu_cookie) ...@@ -31,6 +31,38 @@ static void ocxlflash_destroy_afu(void *afu_cookie)
kfree(afu); kfree(afu);
} }
/**
* ocxlflash_config_fn() - configure the host function
* @pdev: PCI device associated with the host.
* @afu: AFU associated with the host.
*
* Return: 0 on success, -errno on failure
*/
static int ocxlflash_config_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
{
struct ocxl_fn_config *fcfg = &afu->fcfg;
struct device *dev = &pdev->dev;
int rc = 0;
/* Read DVSEC config of the function */
rc = ocxl_config_read_function(pdev, fcfg);
if (unlikely(rc)) {
dev_err(dev, "%s: ocxl_config_read_function failed rc=%d\n",
__func__, rc);
goto out;
}
/* Check if function has AFUs defined, only 1 per function supported */
if (fcfg->max_afu_index >= 0) {
afu->is_present = true;
if (fcfg->max_afu_index != 0)
dev_warn(dev, "%s: Unexpected AFU index value %d\n",
__func__, fcfg->max_afu_index);
}
out:
return rc;
}
/** /**
* ocxlflash_create_afu() - create the AFU for OCXL * ocxlflash_create_afu() - create the AFU for OCXL
* @pdev: PCI device associated with the host. * @pdev: PCI device associated with the host.
...@@ -41,6 +73,7 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev) ...@@ -41,6 +73,7 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct ocxl_hw_afu *afu; struct ocxl_hw_afu *afu;
int rc;
afu = kzalloc(sizeof(*afu), GFP_KERNEL); afu = kzalloc(sizeof(*afu), GFP_KERNEL);
if (unlikely(!afu)) { if (unlikely(!afu)) {
...@@ -50,8 +83,19 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev) ...@@ -50,8 +83,19 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
afu->pdev = pdev; afu->pdev = pdev;
afu->dev = dev; afu->dev = dev;
rc = ocxlflash_config_fn(pdev, afu);
if (unlikely(rc)) {
dev_err(dev, "%s: Function configuration failed rc=%d\n",
__func__, rc);
goto err1;
}
out: out:
return afu; return afu;
err1:
kfree(afu);
afu = NULL;
goto out;
} }
/* Backend ops to ocxlflash services */ /* Backend ops to ocxlflash services */
......
...@@ -16,4 +16,8 @@ ...@@ -16,4 +16,8 @@
struct ocxl_hw_afu { struct ocxl_hw_afu {
struct pci_dev *pdev; /* PCI device */ struct pci_dev *pdev; /* PCI device */
struct device *dev; /* Generic device */ struct device *dev; /* Generic device */
struct ocxl_fn_config fcfg; /* DVSEC config of the function */
bool is_present; /* Function has AFUs defined */
}; };
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