scsi: cxlflash: Use IDR to manage adapter contexts
authorUma Krishnan <ukrishn@linux.vnet.ibm.com>
Mon, 26 Mar 2018 16:32:00 +0000 (11:32 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 18 Apr 2018 23:32:48 +0000 (19:32 -0400)
A range of PASIDs are used as identifiers for the adapter contexts. These
contexts may be destroyed and created randomly. Use an IDR to keep track of
contexts that are in use and assign a unique identifier to new ones.

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>
drivers/scsi/cxlflash/ocxl_hw.c
drivers/scsi/cxlflash/ocxl_hw.h

index cbe4d9341f5a3394a7830afe738fea1be21d9c87..e8864a1f244dcfacf6d4bf0e2a9a01144e5390a4 100644 (file)
@@ -12,6 +12,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/idr.h>
+
 #include <misc/ocxl.h>
 
 #include "backend.h"
@@ -60,14 +62,25 @@ static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
        if (unlikely(!ctx)) {
                dev_err(dev, "%s: Context allocation failed\n", __func__);
                rc = -ENOMEM;
-               goto err;
+               goto err1;
+       }
+
+       idr_preload(GFP_KERNEL);
+       rc = idr_alloc(&afu->idr, ctx, 0, afu->max_pasid, GFP_NOWAIT);
+       idr_preload_end();
+       if (unlikely(rc < 0)) {
+               dev_err(dev, "%s: idr_alloc failed rc=%d\n", __func__, rc);
+               goto err2;
        }
 
+       ctx->pe = rc;
        ctx->master = false;
        ctx->hw_afu = afu;
 out:
        return ctx;
-err:
+err2:
+       kfree(ctx);
+err1:
        ctx = ERR_PTR(rc);
        goto out;
 }
@@ -86,6 +99,7 @@ static int ocxlflash_release_context(void *ctx_cookie)
        if (!ctx)
                goto out;
 
+       idr_remove(&ctx->hw_afu->idr, ctx->pe);
        kfree(ctx);
 out:
        return rc;
@@ -103,6 +117,7 @@ static void ocxlflash_destroy_afu(void *afu_cookie)
                return;
 
        ocxlflash_release_context(afu->ocxl_ctx);
+       idr_destroy(&afu->idr);
        kfree(afu);
 }
 
@@ -221,6 +236,7 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
 
        afu->pdev = pdev;
        afu->dev = dev;
+       idr_init(&afu->idr);
 
        rc = ocxlflash_config_fn(pdev, afu);
        if (unlikely(rc)) {
@@ -248,6 +264,7 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
 out:
        return afu;
 err1:
+       idr_destroy(&afu->idr);
        kfree(afu);
        afu = NULL;
        goto out;
index f41ba0ba23c6257f107cd529b89c72464ebd95c9..a5337b62a557cf9beea008d5fb6736a2f10c2e17 100644 (file)
@@ -26,6 +26,7 @@ struct ocxl_hw_afu {
        int afu_actag_base;             /* AFU acTag base */
        int afu_actag_enabled;          /* AFU acTag number enabled */
 
+       struct idr idr;                 /* IDR to manage contexts */
        int max_pasid;                  /* Maximum number of contexts */
        bool is_present;                /* Function has AFUs defined */
 };
@@ -33,4 +34,5 @@ struct ocxl_hw_afu {
 struct ocxlflash_context {
        struct ocxl_hw_afu *hw_afu;     /* HW AFU back pointer */
        bool master;                    /* Whether this is a master context */
+       int pe;                         /* Process element */
 };