ctxi->file = file;
        ctxi->initialized = true;
        mutex_init(&ctxi->mutex);
+       kref_init(&ctxi->kref);
        INIT_LIST_HEAD(&ctxi->luns);
        INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */
 }
 
+/**
+ * remove_context() - context kref release handler
+ * @kref:      Kernel reference associated with context to be removed.
+ *
+ * When a context no longer has any references it can safely be removed
+ * from global access and destroyed. Note that it is assumed the thread
+ * relinquishing access to the context holds its mutex.
+ */
+static void remove_context(struct kref *kref)
+{
+       struct ctx_info *ctxi = container_of(kref, struct ctx_info, kref);
+       struct cxlflash_cfg *cfg = ctxi->cfg;
+       int lfd;
+       u64 ctxid = DECODE_CTXID(ctxi->ctxid);
+
+       /* Remove context from table/error list */
+       WARN_ON(!mutex_is_locked(&ctxi->mutex));
+       ctxi->unavail = true;
+       mutex_unlock(&ctxi->mutex);
+       mutex_lock(&cfg->ctx_tbl_list_mutex);
+       mutex_lock(&ctxi->mutex);
+
+       if (!list_empty(&ctxi->list))
+               list_del(&ctxi->list);
+       cfg->ctx_tbl[ctxid] = NULL;
+       mutex_unlock(&cfg->ctx_tbl_list_mutex);
+       mutex_unlock(&ctxi->mutex);
+
+       /* Context now completely uncoupled/unreachable */
+       lfd = ctxi->lfd;
+       destroy_context(cfg, ctxi);
+
+       /*
+        * As a last step, clean up external resources when not
+        * already on an external cleanup thread, i.e.: close(adap_fd).
+        *
+        * NOTE: this will free up the context from the CXL services,
+        * allowing it to dole out the same context_id on a future
+        * (or even currently in-flight) disk_attach operation.
+        */
+       if (lfd != -1)
+               sys_close(lfd);
+}
+
 /**
  * _cxlflash_disk_detach() - detaches a LUN from a context
  * @sdev:      SCSI device associated with LUN.
 
        int i;
        int rc = 0;
-       int lfd;
        u64 ctxid = DECODE_CTXID(detach->context_id),
            rctxid = detach->context_id;
 
                        break;
                }
 
-       /* Tear down context following last LUN cleanup */
-       if (list_empty(&ctxi->luns)) {
-               ctxi->unavail = true;
-               mutex_unlock(&ctxi->mutex);
-               mutex_lock(&cfg->ctx_tbl_list_mutex);
-               mutex_lock(&ctxi->mutex);
-
-               /* Might not have been in error list so conditionally remove */
-               if (!list_empty(&ctxi->list))
-                       list_del(&ctxi->list);
-               cfg->ctx_tbl[ctxid] = NULL;
-               mutex_unlock(&cfg->ctx_tbl_list_mutex);
-               mutex_unlock(&ctxi->mutex);
-
-               lfd = ctxi->lfd;
-               destroy_context(cfg, ctxi);
-               ctxi = NULL;
-               put_ctx = false;
-
-               /*
-                * As a last step, clean up external resources when not
-                * already on an external cleanup thread, i.e.: close(adap_fd).
-                *
-                * NOTE: this will free up the context from the CXL services,
-                * allowing it to dole out the same context_id on a future
-                * (or even currently in-flight) disk_attach operation.
-                */
-               if (lfd != -1)
-                       sys_close(lfd);
-       }
-
-       /* Release the sdev reference that bound this LUN to the context */
+       /*
+        * Release the context reference and the sdev reference that
+        * bound this LUN to the context.
+        */
+       put_ctx = !kref_put(&ctxi->kref, remove_context);
        scsi_device_put(sdev);
-
 out:
        if (put_ctx)
                put_context(ctxi);
        lun_access->lli = lli;
        lun_access->sdev = sdev;
 
-       /* Non-NULL context indicates reuse */
+       /* Non-NULL context indicates reuse (another context reference) */
        if (ctxi) {
                dev_dbg(dev, "%s: Reusing context for LUN! (%016llX)\n",
                        __func__, rctxid);
+               kref_get(&ctxi->kref);
                list_add(&lun_access->list, &ctxi->luns);
                fd = ctxi->lfd;
                goto out_attach;