scsi: cxlflash: Hardware AFU for OCXL

When an adapter is initialized, transport specific configuration and MMIO
mapping details need to be saved. For CXL, this data is managed by the
underlying kernel module. To maintain a separation between the cxlflash core
and underlying transports, introduce a new structure to store data specific to
the OCXL AFU.

Initially only the pointers to underlying PCI and generic devices are added to
this new structure - it will be expanded further in future commits. Services
to create and destroy this hardware AFU are added and integrated in the probe
and exit paths of the driver.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Uma Krishnan 2018-03-26 11:31:01 -05:00 committed by Martin K. Petersen
parent 76ebe01fce
commit 48e077dbb4
5 changed files with 73 additions and 2 deletions

View File

@ -36,6 +36,7 @@ struct cxlflash_backend_ops {
int (*allocate_afu_irqs)(void *ctx_cookie, int num); int (*allocate_afu_irqs)(void *ctx_cookie, int num);
void (*free_afu_irqs)(void *ctx_cookie); void (*free_afu_irqs)(void *ctx_cookie);
void * (*create_afu)(struct pci_dev *dev); void * (*create_afu)(struct pci_dev *dev);
void (*destroy_afu)(void *afu_cookie);
struct file * (*get_fd)(void *ctx_cookie, struct file_operations *fops, struct file * (*get_fd)(void *ctx_cookie, struct file_operations *fops,
int *fd); int *fd);
void * (*fops_get_context)(struct file *file); void * (*fops_get_context)(struct file *file);

View File

@ -110,6 +110,11 @@ static void *cxlflash_create_afu(struct pci_dev *dev)
return cxl_pci_to_afu(dev); return cxl_pci_to_afu(dev);
} }
static void cxlflash_destroy_afu(void *afu)
{
/* Dummy fop for cxl */
}
static struct file *cxlflash_get_fd(void *ctx_cookie, static struct file *cxlflash_get_fd(void *ctx_cookie,
struct file_operations *fops, int *fd) struct file_operations *fops, int *fd)
{ {
@ -160,6 +165,7 @@ const struct cxlflash_backend_ops cxlflash_cxl_ops = {
.allocate_afu_irqs = cxlflash_allocate_afu_irqs, .allocate_afu_irqs = cxlflash_allocate_afu_irqs,
.free_afu_irqs = cxlflash_free_afu_irqs, .free_afu_irqs = cxlflash_free_afu_irqs,
.create_afu = cxlflash_create_afu, .create_afu = cxlflash_create_afu,
.destroy_afu = cxlflash_destroy_afu,
.get_fd = cxlflash_get_fd, .get_fd = cxlflash_get_fd,
.fops_get_context = cxlflash_fops_get_context, .fops_get_context = cxlflash_fops_get_context,
.start_work = cxlflash_start_work, .start_work = cxlflash_start_work,

View File

@ -971,6 +971,7 @@ static void cxlflash_remove(struct pci_dev *pdev)
case INIT_STATE_AFU: case INIT_STATE_AFU:
term_afu(cfg); term_afu(cfg);
case INIT_STATE_PCI: case INIT_STATE_PCI:
cfg->ops->destroy_afu(cfg->afu_cookie);
pci_disable_device(pdev); pci_disable_device(pdev);
case INIT_STATE_NONE: case INIT_STATE_NONE:
free_mem(cfg); free_mem(cfg);
@ -3689,8 +3690,6 @@ static int cxlflash_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, cfg); pci_set_drvdata(pdev, cfg);
cfg->afu_cookie = cfg->ops->create_afu(pdev);
rc = init_pci(cfg); rc = init_pci(cfg);
if (rc) { if (rc) {
dev_err(dev, "%s: init_pci failed rc=%d\n", __func__, rc); dev_err(dev, "%s: init_pci failed rc=%d\n", __func__, rc);
@ -3698,6 +3697,12 @@ static int cxlflash_probe(struct pci_dev *pdev,
} }
cfg->init_state = INIT_STATE_PCI; cfg->init_state = INIT_STATE_PCI;
cfg->afu_cookie = cfg->ops->create_afu(pdev);
if (unlikely(!cfg->afu_cookie)) {
dev_err(dev, "%s: create_afu failed\n", __func__);
goto out_remove;
}
rc = init_afu(cfg); rc = init_afu(cfg);
if (rc && !wq_has_sleeper(&cfg->reset_waitq)) { if (rc && !wq_has_sleeper(&cfg->reset_waitq)) {
dev_err(dev, "%s: init_afu failed rc=%d\n", __func__, rc); dev_err(dev, "%s: init_afu failed rc=%d\n", __func__, rc);

View File

@ -15,8 +15,48 @@
#include <misc/ocxl.h> #include <misc/ocxl.h>
#include "backend.h" #include "backend.h"
#include "ocxl_hw.h"
/**
* ocxlflash_destroy_afu() - destroy the AFU structure
* @afu_cookie: AFU to be freed.
*/
static void ocxlflash_destroy_afu(void *afu_cookie)
{
struct ocxl_hw_afu *afu = afu_cookie;
if (!afu)
return;
kfree(afu);
}
/**
* ocxlflash_create_afu() - create the AFU for OCXL
* @pdev: PCI device associated with the host.
*
* Return: AFU on success, NULL on failure
*/
static void *ocxlflash_create_afu(struct pci_dev *pdev)
{
struct device *dev = &pdev->dev;
struct ocxl_hw_afu *afu;
afu = kzalloc(sizeof(*afu), GFP_KERNEL);
if (unlikely(!afu)) {
dev_err(dev, "%s: HW AFU allocation failed\n", __func__);
goto out;
}
afu->pdev = pdev;
afu->dev = dev;
out:
return afu;
}
/* Backend ops to ocxlflash services */ /* Backend ops to ocxlflash services */
const struct cxlflash_backend_ops cxlflash_ocxl_ops = { const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.create_afu = ocxlflash_create_afu,
.destroy_afu = ocxlflash_destroy_afu,
}; };

View File

@ -0,0 +1,19 @@
/*
* CXL Flash Device Driver
*
* Written by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
* Uma Krishnan <ukrishn@linux.vnet.ibm.com>, IBM Corporation
*
* Copyright (C) 2018 IBM Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
/* OCXL hardware AFU associated with the host */
struct ocxl_hw_afu {
struct pci_dev *pdev; /* PCI device */
struct device *dev; /* Generic device */
};