From 48e077dbb41d8ddc2ba5af7a60af4c56302ea8c7 Mon Sep 17 00:00:00 2001 From: Uma Krishnan Date: Mon, 26 Mar 2018 11:31:01 -0500 Subject: [PATCH] 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 Acked-by: Matthew R. Ochs Reviewed-by: Andrew Donnellan Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/backend.h | 1 + drivers/scsi/cxlflash/cxl_hw.c | 6 +++++ drivers/scsi/cxlflash/main.c | 9 ++++++-- drivers/scsi/cxlflash/ocxl_hw.c | 40 +++++++++++++++++++++++++++++++++ drivers/scsi/cxlflash/ocxl_hw.h | 19 ++++++++++++++++ 5 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 drivers/scsi/cxlflash/ocxl_hw.h diff --git a/drivers/scsi/cxlflash/backend.h b/drivers/scsi/cxlflash/backend.h index a60f0516090b..f675bcb4f153 100644 --- a/drivers/scsi/cxlflash/backend.h +++ b/drivers/scsi/cxlflash/backend.h @@ -36,6 +36,7 @@ struct cxlflash_backend_ops { int (*allocate_afu_irqs)(void *ctx_cookie, int num); void (*free_afu_irqs)(void *ctx_cookie); void * (*create_afu)(struct pci_dev *dev); + void (*destroy_afu)(void *afu_cookie); struct file * (*get_fd)(void *ctx_cookie, struct file_operations *fops, int *fd); void * (*fops_get_context)(struct file *file); diff --git a/drivers/scsi/cxlflash/cxl_hw.c b/drivers/scsi/cxlflash/cxl_hw.c index db1cadad5c5d..a1d6d12090d3 100644 --- a/drivers/scsi/cxlflash/cxl_hw.c +++ b/drivers/scsi/cxlflash/cxl_hw.c @@ -110,6 +110,11 @@ static void *cxlflash_create_afu(struct pci_dev *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, 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, .free_afu_irqs = cxlflash_free_afu_irqs, .create_afu = cxlflash_create_afu, + .destroy_afu = cxlflash_destroy_afu, .get_fd = cxlflash_get_fd, .fops_get_context = cxlflash_fops_get_context, .start_work = cxlflash_start_work, diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index b83a55a93ba6..5d754d1c22a0 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -971,6 +971,7 @@ static void cxlflash_remove(struct pci_dev *pdev) case INIT_STATE_AFU: term_afu(cfg); case INIT_STATE_PCI: + cfg->ops->destroy_afu(cfg->afu_cookie); pci_disable_device(pdev); case INIT_STATE_NONE: free_mem(cfg); @@ -3689,8 +3690,6 @@ static int cxlflash_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, cfg); - cfg->afu_cookie = cfg->ops->create_afu(pdev); - rc = init_pci(cfg); if (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->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); if (rc && !wq_has_sleeper(&cfg->reset_waitq)) { dev_err(dev, "%s: init_afu failed rc=%d\n", __func__, rc); diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c index 58a31822d936..e3a0a9b42e8f 100644 --- a/drivers/scsi/cxlflash/ocxl_hw.c +++ b/drivers/scsi/cxlflash/ocxl_hw.c @@ -15,8 +15,48 @@ #include #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 */ const struct cxlflash_backend_ops cxlflash_ocxl_ops = { .module = THIS_MODULE, + .create_afu = ocxlflash_create_afu, + .destroy_afu = ocxlflash_destroy_afu, }; diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h new file mode 100644 index 000000000000..c7e5c4dba49c --- /dev/null +++ b/drivers/scsi/cxlflash/ocxl_hw.h @@ -0,0 +1,19 @@ +/* + * CXL Flash Device Driver + * + * Written by: Matthew R. Ochs , IBM Corporation + * Uma Krishnan , 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 */ +};