All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver
@ 2022-05-10 20:00 James Smart
  2022-05-10 20:00 ` [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: James Smart @ 2022-05-10 20:00 UTC (permalink / raw)
  To: linux-scsi; +Cc: linux-nvme, James Smart

This patch adds vmid support to the nvme-fc transport.

Various virtualization technologies used in Fibre Channel
SAN deployments have the ability to identify and associate traffic
with specific virtualized applications. The T11 standard defines
an application services tag that can be added to FC traffic to aid
in identification and monitoring of traffic associated with the
applications.

VMID support is present in the kernel in blkcg, the SCSI fc transport
has tied into the infrastructure, and libvirt has been
updated to support the blkcg settings.  Refer to:
https://lore.kernel.org/all/20210608043556.274139-1-muneendra.kumar@broadcom.com/

This patch set ties the nvme-fc transport into the blkcg infrastructure
so that vmid tags can be added to nvme traffic. The patch set also
updates the lpfc driver to utilize the nvme-fc transport addition.

Although the patch adds a nvme interface, it is being sent to the SCSI
maintainers tree due to the lpfc dependencies.  As there is no other
consumer of the new interface, when the scsi tree merges with mainline,
the new interface will be picked up there.

Patches cut against scsi 5.19/scsi-queue tree with lpfc 14.2.0.3 patches
included.

James Smart (3):
  lpfc: commonize VMID code location
  lpfc: rework lpfc_vmid_get_appid() to be protocol independent
  lpfc: Add support for vmid tagging of NVMe I/Os

Muneendra (1):
  nvme-fc: Add new routine nvme_fc_io_getuuid

 drivers/nvme/host/fc.c         |  16 ++
 drivers/scsi/lpfc/Makefile     |   2 +-
 drivers/scsi/lpfc/lpfc_crtn.h  |   3 +
 drivers/scsi/lpfc/lpfc_nvme.c  |  45 ++++++
 drivers/scsi/lpfc/lpfc_scsi.c  | 263 +-----------------------------
 drivers/scsi/lpfc/lpfc_vmid.c  | 288 +++++++++++++++++++++++++++++++++
 include/linux/nvme-fc-driver.h |  14 ++
 7 files changed, 371 insertions(+), 260 deletions(-)
 create mode 100644 drivers/scsi/lpfc/lpfc_vmid.c

-- 
2.26.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid
  2022-05-10 20:00 [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
@ 2022-05-10 20:00 ` James Smart
  2022-05-12  9:50   ` Hannes Reinecke
                     ` (2 more replies)
  2022-05-10 20:00 ` [PATCH 2/4] lpfc: commonize VMID code location James Smart
                   ` (3 subsequent siblings)
  4 siblings, 3 replies; 15+ messages in thread
From: James Smart @ 2022-05-10 20:00 UTC (permalink / raw)
  To: linux-scsi; +Cc: linux-nvme, Muneendra, James Smart

From: Muneendra <muneendra.kumar@broadcom.com>

Add nvme_fc_io_getuuid() to the nvme-fc transport.
The routine is invoked by the fc LLDD on a per-io request basis.
The routine translates from the fc-specific request structure to
the bio and the cgroup structure in order to obtain the fc appid
stored in the cgroup structure. If a value is not set or a bio
is not found, a NULL appid (aka uuid) will be returned to the LLDD.

Signed-off-by: Muneendra <muneendra.kumar@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
---
 drivers/nvme/host/fc.c         | 16 ++++++++++++++++
 include/linux/nvme-fc-driver.h | 14 ++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index 080f85f4105f..a484fe228cd5 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -1899,6 +1899,22 @@ nvme_fc_ctrl_ioerr_work(struct work_struct *work)
 	nvme_fc_error_recovery(ctrl, "transport detected io error");
 }
 
+/*
+ * nvme_fc_io_getuuid - Routine called to get the appid field
+ * associated with request by the lldd
+ * @req:IO request from nvme fc to driver
+ * Returns: UUID if there is an appid associated with VM or
+ * NULL if the user/libvirt has not set the appid to VM
+ */
+char *nvme_fc_io_getuuid(struct nvmefc_fcp_req *req)
+{
+	struct nvme_fc_fcp_op *op = fcp_req_to_fcp_op(req);
+	struct request *rq = op->rq;
+
+	return rq->bio ? blkcg_get_fc_appid(rq->bio) : NULL;
+}
+EXPORT_SYMBOL_GPL(nvme_fc_io_getuuid);
+
 static void
 nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
 {
diff --git a/include/linux/nvme-fc-driver.h b/include/linux/nvme-fc-driver.h
index 5358a5facdee..fa092b9be2fd 100644
--- a/include/linux/nvme-fc-driver.h
+++ b/include/linux/nvme-fc-driver.h
@@ -564,6 +564,15 @@ int nvme_fc_rcv_ls_req(struct nvme_fc_remote_port *remoteport,
 			void *lsreqbuf, u32 lsreqbuf_len);
 
 
+/*
+ * Routine called to get the appid field associated with request by the lldd
+ *
+ * If the return value is NULL : the user/libvirt has not set the appid to VM
+ * If the return value is non-zero: Returns the appid associated with VM
+ *
+ * @req: IO request from nvme fc to driver
+ */
+char *nvme_fc_io_getuuid(struct nvmefc_fcp_req *req);
 
 /*
  * ***************  LLDD FC-NVME Target/Subsystem API ***************
@@ -1048,5 +1057,10 @@ int nvmet_fc_rcv_fcp_req(struct nvmet_fc_target_port *tgtport,
 
 void nvmet_fc_rcv_fcp_abort(struct nvmet_fc_target_port *tgtport,
 			struct nvmefc_tgt_fcp_req *fcpreq);
+/*
+ * add a define, visible to the compiler, that indicates support
+ * for feature. Allows for conditional compilation in LLDDs.
+ */
+#define NVME_FC_FEAT_UUID	0x0001
 
 #endif /* _NVME_FC_DRIVER_H */
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/4] lpfc: commonize VMID code location
  2022-05-10 20:00 [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
  2022-05-10 20:00 ` [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
@ 2022-05-10 20:00 ` James Smart
  2022-05-12  9:50   ` Hannes Reinecke
  2022-05-12 23:45   ` Himanshu Madhani
  2022-05-10 20:00 ` [PATCH 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent James Smart
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 15+ messages in thread
From: James Smart @ 2022-05-10 20:00 UTC (permalink / raw)
  To: linux-scsi; +Cc: linux-nvme, James Smart, Gaurav Srivastava

Remove VMID code from its scsi-specific location and move to a new
file solely for VMID code.

Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
---
 drivers/scsi/lpfc/Makefile    |   2 +-
 drivers/scsi/lpfc/lpfc_crtn.h |   2 +
 drivers/scsi/lpfc/lpfc_scsi.c | 256 ------------------------------
 drivers/scsi/lpfc/lpfc_vmid.c | 288 ++++++++++++++++++++++++++++++++++
 4 files changed, 291 insertions(+), 257 deletions(-)
 create mode 100644 drivers/scsi/lpfc/lpfc_vmid.c

diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile
index 092a971d066b..bbd1faf41e80 100644
--- a/drivers/scsi/lpfc/Makefile
+++ b/drivers/scsi/lpfc/Makefile
@@ -33,4 +33,4 @@ obj-$(CONFIG_SCSI_LPFC) := lpfc.o
 lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o \
 	lpfc_hbadisc.o	lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o   \
 	lpfc_scsi.o lpfc_attr.o lpfc_vport.o lpfc_debugfs.o lpfc_bsg.o \
-	lpfc_nvme.o lpfc_nvmet.o
+	lpfc_nvme.o lpfc_nvmet.o lpfc_vmid.o
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index b0775be31d5c..913844f01bf5 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -671,6 +671,8 @@ int lpfc_vmid_cmd(struct lpfc_vport *vport,
 int lpfc_vmid_hash_fn(const char *vmid, int len);
 struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
 					      uint32_t hash, uint8_t *buf);
+int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct
+			       scsi_cmnd * cmd, union lpfc_vmid_io_tag *tag);
 void lpfc_vmid_vport_cleanup(struct lpfc_vport *vport);
 int lpfc_issue_els_qfpa(struct lpfc_vport *vport);
 
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 1d134a01ff3e..70d0a4d3d92e 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -87,14 +87,6 @@ static void
 lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *psb);
 static int
 lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc);
-static void
-lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash,
-			   struct lpfc_vmid *vmp);
-static void lpfc_vmid_update_entry(struct lpfc_vport *vport, struct scsi_cmnd
-				   *cmd, struct lpfc_vmid *vmp,
-				   union lpfc_vmid_io_tag *tag);
-static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport,
-				    struct lpfc_vmid *vmid);
 
 /**
  * lpfc_sli4_set_rsp_sgl_last - Set the last bit in the response sge.
@@ -5270,254 +5262,6 @@ void lpfc_poll_timeout(struct timer_list *t)
 	}
 }
 
-/*
- * lpfc_get_vmid_from_hashtable - search the UUID in the hash table
- * @vport: The virtual port for which this call is being executed.
- * @hash: calculated hash value
- * @buf: uuid associated with the VE
- * Return the VMID entry associated with the UUID
- * Make sure to acquire the appropriate lock before invoking this routine.
- */
-struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
-					      u32 hash, u8 *buf)
-{
-	struct lpfc_vmid *vmp;
-
-	hash_for_each_possible(vport->hash_table, vmp, hnode, hash) {
-		if (memcmp(&vmp->host_vmid[0], buf, 16) == 0)
-			return vmp;
-	}
-	return NULL;
-}
-
-/*
- * lpfc_put_vmid_in_hashtable - put the VMID in the hash table
- * @vport: The virtual port for which this call is being executed.
- * @hash - calculated hash value
- * @vmp: Pointer to a VMID entry representing a VM sending I/O
- *
- * This routine will insert the newly acquired VMID entity in the hash table.
- * Make sure to acquire the appropriate lock before invoking this routine.
- */
-static void
-lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash,
-			   struct lpfc_vmid *vmp)
-{
-	hash_add(vport->hash_table, &vmp->hnode, hash);
-}
-
-/*
- * lpfc_vmid_hash_fn - create a hash value of the UUID
- * @vmid: uuid associated with the VE
- * @len: length of the VMID string
- * Returns the calculated hash value
- */
-int lpfc_vmid_hash_fn(const char *vmid, int len)
-{
-	int c;
-	int hash = 0;
-
-	if (len == 0)
-		return 0;
-	while (len--) {
-		c = *vmid++;
-		if (c >= 'A' && c <= 'Z')
-			c += 'a' - 'A';
-
-		hash = (hash + (c << LPFC_VMID_HASH_SHIFT) +
-			(c >> LPFC_VMID_HASH_SHIFT)) * 19;
-	}
-
-	return hash & LPFC_VMID_HASH_MASK;
-}
-
-/*
- * lpfc_vmid_update_entry - update the vmid entry in the hash table
- * @vport: The virtual port for which this call is being executed.
- * @cmd: address of scsi cmd descriptor
- * @vmp: Pointer to a VMID entry representing a VM sending I/O
- * @tag: VMID tag
- */
-static void lpfc_vmid_update_entry(struct lpfc_vport *vport, struct scsi_cmnd
-				   *cmd, struct lpfc_vmid *vmp,
-				   union lpfc_vmid_io_tag *tag)
-{
-	u64 *lta;
-
-	if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
-		tag->cs_ctl_vmid = vmp->un.cs_ctl_vmid;
-	else if (vport->phba->cfg_vmid_app_header)
-		tag->app_id = vmp->un.app_id;
-
-	if (cmd->sc_data_direction == DMA_TO_DEVICE)
-		vmp->io_wr_cnt++;
-	else
-		vmp->io_rd_cnt++;
-
-	/* update the last access timestamp in the table */
-	lta = per_cpu_ptr(vmp->last_io_time, raw_smp_processor_id());
-	*lta = jiffies;
-}
-
-static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport,
-				    struct lpfc_vmid *vmid)
-{
-	u32 hash;
-	struct lpfc_vmid *pvmid;
-
-	if (vport->port_type == LPFC_PHYSICAL_PORT) {
-		vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
-	} else {
-		hash = lpfc_vmid_hash_fn(vmid->host_vmid, vmid->vmid_len);
-		pvmid =
-		    lpfc_get_vmid_from_hashtable(vport->phba->pport, hash,
-						vmid->host_vmid);
-		if (pvmid)
-			vmid->un.cs_ctl_vmid = pvmid->un.cs_ctl_vmid;
-		else
-			vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
-	}
-}
-
-/*
- * lpfc_vmid_get_appid - get the VMID associated with the UUID
- * @vport: The virtual port for which this call is being executed.
- * @uuid: UUID associated with the VE
- * @cmd: address of scsi_cmd descriptor
- * @tag: VMID tag
- * Returns status of the function
- */
-static int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct
-			       scsi_cmnd * cmd, union lpfc_vmid_io_tag *tag)
-{
-	struct lpfc_vmid *vmp = NULL;
-	int hash, len, rc = -EPERM, i;
-
-	/* check if QFPA is complete */
-	if (lpfc_vmid_is_type_priority_tag(vport) &&
-	    !(vport->vmid_flag & LPFC_VMID_QFPA_CMPL) &&
-	    (vport->vmid_flag & LPFC_VMID_ISSUE_QFPA)) {
-		vport->work_port_events |= WORKER_CHECK_VMID_ISSUE_QFPA;
-		return -EAGAIN;
-	}
-
-	/* search if the UUID has already been mapped to the VMID */
-	len = strlen(uuid);
-	hash = lpfc_vmid_hash_fn(uuid, len);
-
-	/* search for the VMID in the table */
-	read_lock(&vport->vmid_lock);
-	vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
-
-	/* if found, check if its already registered  */
-	if (vmp  && vmp->flag & LPFC_VMID_REGISTERED) {
-		read_unlock(&vport->vmid_lock);
-		lpfc_vmid_update_entry(vport, cmd, vmp, tag);
-		rc = 0;
-	} else if (vmp && (vmp->flag & LPFC_VMID_REQ_REGISTER ||
-			   vmp->flag & LPFC_VMID_DE_REGISTER)) {
-		/* else if register or dereg request has already been sent */
-		/* Hence VMID tag will not be added for this I/O */
-		read_unlock(&vport->vmid_lock);
-		rc = -EBUSY;
-	} else {
-		/* The VMID was not found in the hashtable. At this point, */
-		/* drop the read lock first before proceeding further */
-		read_unlock(&vport->vmid_lock);
-		/* start the process to obtain one as per the */
-		/* type of the VMID indicated */
-		write_lock(&vport->vmid_lock);
-		vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
-
-		/* while the read lock was released, in case the entry was */
-		/* added by other context or is in process of being added */
-		if (vmp && vmp->flag & LPFC_VMID_REGISTERED) {
-			lpfc_vmid_update_entry(vport, cmd, vmp, tag);
-			write_unlock(&vport->vmid_lock);
-			return 0;
-		} else if (vmp && vmp->flag & LPFC_VMID_REQ_REGISTER) {
-			write_unlock(&vport->vmid_lock);
-			return -EBUSY;
-		}
-
-		/* else search and allocate a free slot in the hash table */
-		if (vport->cur_vmid_cnt < vport->max_vmid) {
-			for (i = 0; i < vport->max_vmid; i++) {
-				vmp = vport->vmid + i;
-				if (vmp->flag == LPFC_VMID_SLOT_FREE)
-					break;
-			}
-			if (i == vport->max_vmid)
-				vmp = NULL;
-		} else {
-			vmp = NULL;
-		}
-
-		if (!vmp) {
-			write_unlock(&vport->vmid_lock);
-			return -ENOMEM;
-		}
-
-		/* Add the vmid and register */
-		lpfc_put_vmid_in_hashtable(vport, hash, vmp);
-		vmp->vmid_len = len;
-		memcpy(vmp->host_vmid, uuid, vmp->vmid_len);
-		vmp->io_rd_cnt = 0;
-		vmp->io_wr_cnt = 0;
-		vmp->flag = LPFC_VMID_SLOT_USED;
-
-		vmp->delete_inactive =
-			vport->vmid_inactivity_timeout ? 1 : 0;
-
-		/* if type priority tag, get next available VMID */
-		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
-			lpfc_vmid_assign_cs_ctl(vport, vmp);
-
-		/* allocate the per cpu variable for holding */
-		/* the last access time stamp only if VMID is enabled */
-		if (!vmp->last_io_time)
-			vmp->last_io_time = __alloc_percpu(sizeof(u64),
-							   __alignof__(struct
-							   lpfc_vmid));
-		if (!vmp->last_io_time) {
-			hash_del(&vmp->hnode);
-			vmp->flag = LPFC_VMID_SLOT_FREE;
-			write_unlock(&vport->vmid_lock);
-			return -EIO;
-		}
-
-		write_unlock(&vport->vmid_lock);
-
-		/* complete transaction with switch */
-		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
-			rc = lpfc_vmid_uvem(vport, vmp, true);
-		else if (vport->phba->cfg_vmid_app_header)
-			rc = lpfc_vmid_cmd(vport, SLI_CTAS_RAPP_IDENT, vmp);
-		if (!rc) {
-			write_lock(&vport->vmid_lock);
-			vport->cur_vmid_cnt++;
-			vmp->flag |= LPFC_VMID_REQ_REGISTER;
-			write_unlock(&vport->vmid_lock);
-		} else {
-			write_lock(&vport->vmid_lock);
-			hash_del(&vmp->hnode);
-			vmp->flag = LPFC_VMID_SLOT_FREE;
-			free_percpu(vmp->last_io_time);
-			write_unlock(&vport->vmid_lock);
-			return -EIO;
-		}
-
-		/* finally, enable the idle timer once */
-		if (!(vport->phba->pport->vmid_flag & LPFC_VMID_TIMER_ENBLD)) {
-			mod_timer(&vport->phba->inactive_vmid_poll,
-				  jiffies +
-				  msecs_to_jiffies(1000 * LPFC_VMID_TIMER));
-			vport->phba->pport->vmid_flag |= LPFC_VMID_TIMER_ENBLD;
-		}
-	}
-	return rc;
-}
-
 /*
  * lpfc_is_command_vm_io - get the UUID from blk cgroup
  * @cmd: Pointer to scsi_cmnd data structure
diff --git a/drivers/scsi/lpfc/lpfc_vmid.c b/drivers/scsi/lpfc/lpfc_vmid.c
new file mode 100644
index 000000000000..f64ced04b912
--- /dev/null
+++ b/drivers/scsi/lpfc/lpfc_vmid.c
@@ -0,0 +1,288 @@
+/*******************************************************************
+ * This file is part of the Emulex Linux Device Driver for         *
+ * Fibre Channel Host Bus Adapters.                                *
+ * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
+ * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
+ * EMULEX and SLI are trademarks of Emulex.                        *
+ * www.broadcom.com                                                *
+ * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
+ *                                                                 *
+ * This program is free software; you can redistribute it and/or   *
+ * modify it under the terms of version 2 of the GNU General       *
+ * Public License as published by the Free Software Foundation.    *
+ * This program is distributed in the hope that it will be useful. *
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+ * more details, a copy of which can be found in the file COPYING  *
+ * included with this package.                                     *
+ *******************************************************************/
+
+#include <linux/interrupt.h>
+#include <linux/dma-direction.h>
+
+#include <scsi/scsi_transport_fc.h>
+
+#include "lpfc_hw4.h"
+#include "lpfc_hw.h"
+#include "lpfc_sli.h"
+#include "lpfc_sli4.h"
+#include "lpfc_nl.h"
+#include "lpfc_disc.h"
+#include "lpfc.h"
+#include "lpfc_crtn.h"
+
+
+/*
+ * lpfc_get_vmid_from_hashtable - search the UUID in the hash table
+ * @vport: The virtual port for which this call is being executed.
+ * @hash: calculated hash value
+ * @buf: uuid associated with the VE
+ * Return the VMID entry associated with the UUID
+ * Make sure to acquire the appropriate lock before invoking this routine.
+ */
+struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
+					       u32 hash, u8 *buf)
+{
+	struct lpfc_vmid *vmp;
+
+	hash_for_each_possible(vport->hash_table, vmp, hnode, hash) {
+		if (memcmp(&vmp->host_vmid[0], buf, 16) == 0)
+			return vmp;
+	}
+	return NULL;
+}
+
+/*
+ * lpfc_put_vmid_in_hashtable - put the VMID in the hash table
+ * @vport: The virtual port for which this call is being executed.
+ * @hash - calculated hash value
+ * @vmp: Pointer to a VMID entry representing a VM sending I/O
+ *
+ * This routine will insert the newly acquired VMID entity in the hash table.
+ * Make sure to acquire the appropriate lock before invoking this routine.
+ */
+static void
+lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash,
+			   struct lpfc_vmid *vmp)
+{
+	hash_add(vport->hash_table, &vmp->hnode, hash);
+}
+
+/*
+ * lpfc_vmid_hash_fn - create a hash value of the UUID
+ * @vmid: uuid associated with the VE
+ * @len: length of the VMID string
+ * Returns the calculated hash value
+ */
+int lpfc_vmid_hash_fn(const char *vmid, int len)
+{
+	int c;
+	int hash = 0;
+
+	if (len == 0)
+		return 0;
+	while (len--) {
+		c = *vmid++;
+		if (c >= 'A' && c <= 'Z')
+			c += 'a' - 'A';
+
+		hash = (hash + (c << LPFC_VMID_HASH_SHIFT) +
+			(c >> LPFC_VMID_HASH_SHIFT)) * 19;
+	}
+
+	return hash & LPFC_VMID_HASH_MASK;
+}
+
+/*
+ * lpfc_vmid_update_entry - update the vmid entry in the hash table
+ * @vport: The virtual port for which this call is being executed.
+ * @iodir: io direction
+ * @vmp: Pointer to a VMID entry representing a VM sending I/O
+ * @tag: VMID tag
+ */
+static void lpfc_vmid_update_entry(struct lpfc_vport *vport,
+				   enum dma_data_direction iodir,
+				   struct lpfc_vmid *vmp,
+				   union lpfc_vmid_io_tag *tag)
+{
+	u64 *lta;
+
+	if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
+		tag->cs_ctl_vmid = vmp->un.cs_ctl_vmid;
+	else if (vport->phba->cfg_vmid_app_header)
+		tag->app_id = vmp->un.app_id;
+
+	if (iodir == DMA_TO_DEVICE)
+		vmp->io_wr_cnt++;
+	else if (iodir == DMA_FROM_DEVICE)
+		vmp->io_rd_cnt++;
+
+	/* update the last access timestamp in the table */
+	lta = per_cpu_ptr(vmp->last_io_time, raw_smp_processor_id());
+	*lta = jiffies;
+}
+
+static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport,
+				    struct lpfc_vmid *vmid)
+{
+	u32 hash;
+	struct lpfc_vmid *pvmid;
+
+	if (vport->port_type == LPFC_PHYSICAL_PORT) {
+		vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
+	} else {
+		hash = lpfc_vmid_hash_fn(vmid->host_vmid, vmid->vmid_len);
+		pvmid =
+		    lpfc_get_vmid_from_hashtable(vport->phba->pport, hash,
+						 vmid->host_vmid);
+		if (pvmid)
+			vmid->un.cs_ctl_vmid = pvmid->un.cs_ctl_vmid;
+		else
+			vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
+	}
+}
+
+/*
+ * lpfc_vmid_get_appid - get the VMID associated with the UUID
+ * @vport: The virtual port for which this call is being executed.
+ * @uuid: UUID associated with the VE
+ * @cmd: address of scsi_cmd descriptor
+ * @iodir: io direction
+ * @tag: VMID tag
+ * Returns status of the function
+ */
+int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid,
+			enum dma_data_direction iodir,
+			union lpfc_vmid_io_tag *tag)
+{
+	struct lpfc_vmid *vmp = NULL;
+	int hash, len, rc = -EPERM, i;
+
+	/* check if QFPA is complete */
+	if (lpfc_vmid_is_type_priority_tag(vport) &&
+	    !(vport->vmid_flag & LPFC_VMID_QFPA_CMPL) &&
+	    (vport->vmid_flag & LPFC_VMID_ISSUE_QFPA)) {
+		vport->work_port_events |= WORKER_CHECK_VMID_ISSUE_QFPA;
+		return -EAGAIN;
+	}
+
+	/* search if the UUID has already been mapped to the VMID */
+	len = strlen(uuid);
+	hash = lpfc_vmid_hash_fn(uuid, len);
+
+	/* search for the VMID in the table */
+	read_lock(&vport->vmid_lock);
+	vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
+
+	/* if found, check if its already registered  */
+	if (vmp  && vmp->flag & LPFC_VMID_REGISTERED) {
+		read_unlock(&vport->vmid_lock);
+		lpfc_vmid_update_entry(vport, iodir, vmp, tag);
+		rc = 0;
+	} else if (vmp && (vmp->flag & LPFC_VMID_REQ_REGISTER ||
+			   vmp->flag & LPFC_VMID_DE_REGISTER)) {
+		/* else if register or dereg request has already been sent */
+		/* Hence VMID tag will not be added for this I/O */
+		read_unlock(&vport->vmid_lock);
+		rc = -EBUSY;
+	} else {
+		/* The VMID was not found in the hashtable. At this point, */
+		/* drop the read lock first before proceeding further */
+		read_unlock(&vport->vmid_lock);
+		/* start the process to obtain one as per the */
+		/* type of the VMID indicated */
+		write_lock(&vport->vmid_lock);
+		vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
+
+		/* while the read lock was released, in case the entry was */
+		/* added by other context or is in process of being added */
+		if (vmp && vmp->flag & LPFC_VMID_REGISTERED) {
+			lpfc_vmid_update_entry(vport, iodir, vmp, tag);
+			write_unlock(&vport->vmid_lock);
+			return 0;
+		} else if (vmp && vmp->flag & LPFC_VMID_REQ_REGISTER) {
+			write_unlock(&vport->vmid_lock);
+			return -EBUSY;
+		}
+
+		/* else search and allocate a free slot in the hash table */
+		if (vport->cur_vmid_cnt < vport->max_vmid) {
+			for (i = 0; i < vport->max_vmid; i++) {
+				vmp = vport->vmid + i;
+				if (vmp->flag == LPFC_VMID_SLOT_FREE)
+					break;
+			}
+			if (i == vport->max_vmid)
+				vmp = NULL;
+		} else {
+			vmp = NULL;
+		}
+
+		if (!vmp) {
+			write_unlock(&vport->vmid_lock);
+			return -ENOMEM;
+		}
+
+		/* Add the vmid and register */
+		lpfc_put_vmid_in_hashtable(vport, hash, vmp);
+		vmp->vmid_len = len;
+		memcpy(vmp->host_vmid, uuid, vmp->vmid_len);
+		vmp->io_rd_cnt = 0;
+		vmp->io_wr_cnt = 0;
+		vmp->flag = LPFC_VMID_SLOT_USED;
+
+		vmp->delete_inactive =
+			vport->vmid_inactivity_timeout ? 1 : 0;
+
+		/* if type priority tag, get next available VMID */
+		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
+			lpfc_vmid_assign_cs_ctl(vport, vmp);
+
+		/* allocate the per cpu variable for holding */
+		/* the last access time stamp only if VMID is enabled */
+		if (!vmp->last_io_time)
+			vmp->last_io_time = __alloc_percpu(sizeof(u64),
+							   __alignof__(struct
+							   lpfc_vmid));
+		if (!vmp->last_io_time) {
+			hash_del(&vmp->hnode);
+			vmp->flag = LPFC_VMID_SLOT_FREE;
+			write_unlock(&vport->vmid_lock);
+			return -EIO;
+		}
+
+		write_unlock(&vport->vmid_lock);
+
+		/* complete transaction with switch */
+		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
+			rc = lpfc_vmid_uvem(vport, vmp, true);
+		else if (vport->phba->cfg_vmid_app_header)
+			rc = lpfc_vmid_cmd(vport, SLI_CTAS_RAPP_IDENT, vmp);
+		if (!rc) {
+			write_lock(&vport->vmid_lock);
+			vport->cur_vmid_cnt++;
+			vmp->flag |= LPFC_VMID_REQ_REGISTER;
+			write_unlock(&vport->vmid_lock);
+		} else {
+			write_lock(&vport->vmid_lock);
+			hash_del(&vmp->hnode);
+			vmp->flag = LPFC_VMID_SLOT_FREE;
+			free_percpu(vmp->last_io_time);
+			write_unlock(&vport->vmid_lock);
+			return -EIO;
+		}
+
+		/* finally, enable the idle timer once */
+		if (!(vport->phba->pport->vmid_flag & LPFC_VMID_TIMER_ENBLD)) {
+			mod_timer(&vport->phba->inactive_vmid_poll,
+				  jiffies +
+				  msecs_to_jiffies(1000 * LPFC_VMID_TIMER));
+			vport->phba->pport->vmid_flag |= LPFC_VMID_TIMER_ENBLD;
+		}
+	}
+	return rc;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent
  2022-05-10 20:00 [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
  2022-05-10 20:00 ` [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
  2022-05-10 20:00 ` [PATCH 2/4] lpfc: commonize VMID code location James Smart
@ 2022-05-10 20:00 ` James Smart
  2022-05-12  9:51   ` Hannes Reinecke
  2022-05-12 23:48   ` Himanshu Madhani
  2022-05-10 20:00 ` [PATCH 4/4] lpfc: Add support for vmid tagging of NVMe I/Os James Smart
  2022-05-17  1:40 ` [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver Martin K. Petersen
  4 siblings, 2 replies; 15+ messages in thread
From: James Smart @ 2022-05-10 20:00 UTC (permalink / raw)
  To: linux-scsi; +Cc: linux-nvme, James Smart, Gaurav Srivastava

Rework lpfc_vmid_get_appid() arguments to remove scsi cmd dependency.
It's now callable by nvme path.

Fixup scsi calling path for arg change.

Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
---
 drivers/scsi/lpfc/lpfc_crtn.h | 5 +++--
 drivers/scsi/lpfc/lpfc_scsi.c | 7 ++++---
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 913844f01bf5..b1be0dd0337a 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -671,8 +671,9 @@ int lpfc_vmid_cmd(struct lpfc_vport *vport,
 int lpfc_vmid_hash_fn(const char *vmid, int len);
 struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
 					      uint32_t hash, uint8_t *buf);
-int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct
-			       scsi_cmnd * cmd, union lpfc_vmid_io_tag *tag);
+int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid,
+			enum dma_data_direction iodir,
+			union lpfc_vmid_io_tag *tag);
 void lpfc_vmid_vport_cleanup(struct lpfc_vport *vport);
 int lpfc_issue_els_qfpa(struct lpfc_vport *vport);
 
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 70d0a4d3d92e..f5f4409e24cd 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -5446,9 +5446,10 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
 		uuid = lpfc_is_command_vm_io(cmnd);
 
 		if (uuid) {
-			err = lpfc_vmid_get_appid(vport, uuid, cmnd,
-				(union lpfc_vmid_io_tag *)
-					&cur_iocbq->vmid_tag);
+			err = lpfc_vmid_get_appid(vport, uuid,
+					cmnd->sc_data_direction,
+					(union lpfc_vmid_io_tag *)
+						&cur_iocbq->vmid_tag);
 			if (!err)
 				cur_iocbq->cmd_flag |= LPFC_IO_VMID;
 		}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/4] lpfc: Add support for vmid tagging of NVMe I/Os
  2022-05-10 20:00 [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
                   ` (2 preceding siblings ...)
  2022-05-10 20:00 ` [PATCH 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent James Smart
@ 2022-05-10 20:00 ` James Smart
  2022-05-12  9:51   ` Hannes Reinecke
  2022-05-12 23:50   ` Himanshu Madhani
  2022-05-17  1:40 ` [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver Martin K. Petersen
  4 siblings, 2 replies; 15+ messages in thread
From: James Smart @ 2022-05-10 20:00 UTC (permalink / raw)
  To: linux-scsi; +Cc: linux-nvme, James Smart, Gaurav Srivastava

Modify the nvme io path to look for vmid support and call the
transport to obtain the io's appid value.

Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
---
 drivers/scsi/lpfc/lpfc_nvme.c | 45 +++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 5385f4de5523..335e90633933 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -1279,6 +1279,19 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
 
 	/* Words 13 14 15 are for PBDE support */
 
+	/* add the VMID tags as per switch response */
+	if (unlikely(lpfc_ncmd->cur_iocbq.cmd_flag & LPFC_IO_VMID)) {
+		if (phba->pport->vmid_priority_tagging) {
+			bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1);
+			bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com,
+			       lpfc_ncmd->cur_iocbq.vmid_tag.cs_ctl_vmid);
+		} else {
+			bf_set(wqe_appid, &wqe->fcp_iwrite.wqe_com, 1);
+			bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1);
+			wqe->words[31] = lpfc_ncmd->cur_iocbq.vmid_tag.app_id;
+		}
+	}
+
 	pwqeq->vport = vport;
 	return 0;
 }
@@ -1504,6 +1517,11 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
 	struct lpfc_nvme_fcpreq_priv *freqpriv;
 	struct nvme_common_command *sqe;
 	uint64_t start = 0;
+#if (IS_ENABLED(CONFIG_NVME_FC))
+	u8 *uuid = NULL;
+	int err;
+	enum dma_data_direction iodir;
+#endif
 
 	/* Validate pointers. LLDD fault handling with transport does
 	 * have timing races.
@@ -1662,6 +1680,33 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
 	lpfc_ncmd->ndlp = ndlp;
 	lpfc_ncmd->qidx = lpfc_queue_info->qidx;
 
+#if (IS_ENABLED(CONFIG_NVME_FC))
+	/* check the necessary and sufficient condition to support VMID */
+	if (lpfc_is_vmid_enabled(phba) &&
+	    (ndlp->vmid_support ||
+	     phba->pport->vmid_priority_tagging ==
+	     LPFC_VMID_PRIO_TAG_ALL_TARGETS)) {
+		/* is the I/O generated by a VM, get the associated virtual */
+		/* entity id */
+		uuid = nvme_fc_io_getuuid(pnvme_fcreq);
+
+		if (uuid) {
+			if (pnvme_fcreq->io_dir == NVMEFC_FCP_WRITE)
+				iodir = DMA_TO_DEVICE;
+			else if (pnvme_fcreq->io_dir == NVMEFC_FCP_READ)
+				iodir = DMA_FROM_DEVICE;
+			else
+				iodir = DMA_NONE;
+
+			err = lpfc_vmid_get_appid(vport, uuid, iodir,
+					(union lpfc_vmid_io_tag *)
+						&lpfc_ncmd->cur_iocbq.vmid_tag);
+			if (!err)
+				lpfc_ncmd->cur_iocbq.cmd_flag |= LPFC_IO_VMID;
+		}
+	}
+#endif
+
 	/*
 	 * Issue the IO on the WQ indicated by index in the hw_queue_handle.
 	 * This identfier was create in our hardware queue create callback
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid
  2022-05-10 20:00 ` [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
@ 2022-05-12  9:50   ` Hannes Reinecke
  2022-05-12 23:38   ` Himanshu Madhani
  2022-05-16  5:57   ` Christoph Hellwig
  2 siblings, 0 replies; 15+ messages in thread
From: Hannes Reinecke @ 2022-05-12  9:50 UTC (permalink / raw)
  To: James Smart, linux-scsi; +Cc: linux-nvme, Muneendra

On 5/10/22 22:00, James Smart wrote:
> From: Muneendra <muneendra.kumar@broadcom.com>
> 
> Add nvme_fc_io_getuuid() to the nvme-fc transport.
> The routine is invoked by the fc LLDD on a per-io request basis.
> The routine translates from the fc-specific request structure to
> the bio and the cgroup structure in order to obtain the fc appid
> stored in the cgroup structure. If a value is not set or a bio
> is not found, a NULL appid (aka uuid) will be returned to the LLDD.
> 
> Signed-off-by: Muneendra <muneendra.kumar@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
>   drivers/nvme/host/fc.c         | 16 ++++++++++++++++
>   include/linux/nvme-fc-driver.h | 14 ++++++++++++++
>   2 files changed, 30 insertions(+)
> 
Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		           Kernel Storage Architect
hare@suse.de			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/4] lpfc: commonize VMID code location
  2022-05-10 20:00 ` [PATCH 2/4] lpfc: commonize VMID code location James Smart
@ 2022-05-12  9:50   ` Hannes Reinecke
  2022-05-12 23:45   ` Himanshu Madhani
  1 sibling, 0 replies; 15+ messages in thread
From: Hannes Reinecke @ 2022-05-12  9:50 UTC (permalink / raw)
  To: James Smart, linux-scsi; +Cc: linux-nvme, Gaurav Srivastava

On 5/10/22 22:00, James Smart wrote:
> Remove VMID code from its scsi-specific location and move to a new
> file solely for VMID code.
> 
> Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
>   drivers/scsi/lpfc/Makefile    |   2 +-
>   drivers/scsi/lpfc/lpfc_crtn.h |   2 +
>   drivers/scsi/lpfc/lpfc_scsi.c | 256 ------------------------------
>   drivers/scsi/lpfc/lpfc_vmid.c | 288 ++++++++++++++++++++++++++++++++++
>   4 files changed, 291 insertions(+), 257 deletions(-)
>   create mode 100644 drivers/scsi/lpfc/lpfc_vmid.c
> 
Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		           Kernel Storage Architect
hare@suse.de			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent
  2022-05-10 20:00 ` [PATCH 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent James Smart
@ 2022-05-12  9:51   ` Hannes Reinecke
  2022-05-12 23:48   ` Himanshu Madhani
  1 sibling, 0 replies; 15+ messages in thread
From: Hannes Reinecke @ 2022-05-12  9:51 UTC (permalink / raw)
  To: James Smart, linux-scsi; +Cc: linux-nvme, Gaurav Srivastava

On 5/10/22 22:00, James Smart wrote:
> Rework lpfc_vmid_get_appid() arguments to remove scsi cmd dependency.
> It's now callable by nvme path.
> 
> Fixup scsi calling path for arg change.
> 
> Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
>   drivers/scsi/lpfc/lpfc_crtn.h | 5 +++--
>   drivers/scsi/lpfc/lpfc_scsi.c | 7 ++++---
>   2 files changed, 7 insertions(+), 5 deletions(-)
> 
Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		           Kernel Storage Architect
hare@suse.de			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/4] lpfc: Add support for vmid tagging of NVMe I/Os
  2022-05-10 20:00 ` [PATCH 4/4] lpfc: Add support for vmid tagging of NVMe I/Os James Smart
@ 2022-05-12  9:51   ` Hannes Reinecke
  2022-05-12 23:50   ` Himanshu Madhani
  1 sibling, 0 replies; 15+ messages in thread
From: Hannes Reinecke @ 2022-05-12  9:51 UTC (permalink / raw)
  To: James Smart, linux-scsi; +Cc: linux-nvme, Gaurav Srivastava

On 5/10/22 22:00, James Smart wrote:
> Modify the nvme io path to look for vmid support and call the
> transport to obtain the io's appid value.
> 
> Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
>   drivers/scsi/lpfc/lpfc_nvme.c | 45 +++++++++++++++++++++++++++++++++++
>   1 file changed, 45 insertions(+)
> 
Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		           Kernel Storage Architect
hare@suse.de			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid
  2022-05-10 20:00 ` [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
  2022-05-12  9:50   ` Hannes Reinecke
@ 2022-05-12 23:38   ` Himanshu Madhani
  2022-05-16  5:57   ` Christoph Hellwig
  2 siblings, 0 replies; 15+ messages in thread
From: Himanshu Madhani @ 2022-05-12 23:38 UTC (permalink / raw)
  To: James Smart; +Cc: linux-scsi, linux-nvme, Muneendra



> On May 10, 2022, at 1:00 PM, James Smart <jsmart2021@gmail.com> wrote:
> 
> From: Muneendra <muneendra.kumar@broadcom.com>
> 
> Add nvme_fc_io_getuuid() to the nvme-fc transport.
> The routine is invoked by the fc LLDD on a per-io request basis.
> The routine translates from the fc-specific request structure to
> the bio and the cgroup structure in order to obtain the fc appid
> stored in the cgroup structure. If a value is not set or a bio
> is not found, a NULL appid (aka uuid) will be returned to the LLDD.
> 
> Signed-off-by: Muneendra <muneendra.kumar@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
> drivers/nvme/host/fc.c         | 16 ++++++++++++++++
> include/linux/nvme-fc-driver.h | 14 ++++++++++++++
> 2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
> index 080f85f4105f..a484fe228cd5 100644
> --- a/drivers/nvme/host/fc.c
> +++ b/drivers/nvme/host/fc.c
> @@ -1899,6 +1899,22 @@ nvme_fc_ctrl_ioerr_work(struct work_struct *work)
> 	nvme_fc_error_recovery(ctrl, "transport detected io error");
> }
> 
> +/*
> + * nvme_fc_io_getuuid - Routine called to get the appid field
> + * associated with request by the lldd
> + * @req:IO request from nvme fc to driver
> + * Returns: UUID if there is an appid associated with VM or
> + * NULL if the user/libvirt has not set the appid to VM
> + */
> +char *nvme_fc_io_getuuid(struct nvmefc_fcp_req *req)
> +{
> +	struct nvme_fc_fcp_op *op = fcp_req_to_fcp_op(req);
> +	struct request *rq = op->rq;
> +
> +	return rq->bio ? blkcg_get_fc_appid(rq->bio) : NULL;
> +}
> +EXPORT_SYMBOL_GPL(nvme_fc_io_getuuid);
> +
> static void
> nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
> {
> diff --git a/include/linux/nvme-fc-driver.h b/include/linux/nvme-fc-driver.h
> index 5358a5facdee..fa092b9be2fd 100644
> --- a/include/linux/nvme-fc-driver.h
> +++ b/include/linux/nvme-fc-driver.h
> @@ -564,6 +564,15 @@ int nvme_fc_rcv_ls_req(struct nvme_fc_remote_port *remoteport,
> 			void *lsreqbuf, u32 lsreqbuf_len);
> 
> 
> +/*
> + * Routine called to get the appid field associated with request by the lldd
> + *
> + * If the return value is NULL : the user/libvirt has not set the appid to VM
> + * If the return value is non-zero: Returns the appid associated with VM
> + *
> + * @req: IO request from nvme fc to driver
> + */
> +char *nvme_fc_io_getuuid(struct nvmefc_fcp_req *req);
> 
> /*
>  * ***************  LLDD FC-NVME Target/Subsystem API ***************
> @@ -1048,5 +1057,10 @@ int nvmet_fc_rcv_fcp_req(struct nvmet_fc_target_port *tgtport,
> 
> void nvmet_fc_rcv_fcp_abort(struct nvmet_fc_target_port *tgtport,
> 			struct nvmefc_tgt_fcp_req *fcpreq);
> +/*
> + * add a define, visible to the compiler, that indicates support
> + * for feature. Allows for conditional compilation in LLDDs.
> + */
> +#define NVME_FC_FEAT_UUID	0x0001
> 
> #endif /* _NVME_FC_DRIVER_H */
> -- 
> 2.26.2
> 

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>

--
Himanshu Madhani	Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/4] lpfc: commonize VMID code location
  2022-05-10 20:00 ` [PATCH 2/4] lpfc: commonize VMID code location James Smart
  2022-05-12  9:50   ` Hannes Reinecke
@ 2022-05-12 23:45   ` Himanshu Madhani
  1 sibling, 0 replies; 15+ messages in thread
From: Himanshu Madhani @ 2022-05-12 23:45 UTC (permalink / raw)
  To: James Smart; +Cc: linux-scsi, linux-nvme, Gaurav Srivastava



> On May 10, 2022, at 1:00 PM, James Smart <jsmart2021@gmail.com> wrote:
> 
> Remove VMID code from its scsi-specific location and move to a new
> file solely for VMID code.
> 
> Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
> drivers/scsi/lpfc/Makefile    |   2 +-
> drivers/scsi/lpfc/lpfc_crtn.h |   2 +
> drivers/scsi/lpfc/lpfc_scsi.c | 256 ------------------------------
> drivers/scsi/lpfc/lpfc_vmid.c | 288 ++++++++++++++++++++++++++++++++++
> 4 files changed, 291 insertions(+), 257 deletions(-)
> create mode 100644 drivers/scsi/lpfc/lpfc_vmid.c
> 
> diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile
> index 092a971d066b..bbd1faf41e80 100644
> --- a/drivers/scsi/lpfc/Makefile
> +++ b/drivers/scsi/lpfc/Makefile
> @@ -33,4 +33,4 @@ obj-$(CONFIG_SCSI_LPFC) := lpfc.o
> lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o \
> 	lpfc_hbadisc.o	lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o   \
> 	lpfc_scsi.o lpfc_attr.o lpfc_vport.o lpfc_debugfs.o lpfc_bsg.o \
> -	lpfc_nvme.o lpfc_nvmet.o
> +	lpfc_nvme.o lpfc_nvmet.o lpfc_vmid.o
> diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
> index b0775be31d5c..913844f01bf5 100644
> --- a/drivers/scsi/lpfc/lpfc_crtn.h
> +++ b/drivers/scsi/lpfc/lpfc_crtn.h
> @@ -671,6 +671,8 @@ int lpfc_vmid_cmd(struct lpfc_vport *vport,
> int lpfc_vmid_hash_fn(const char *vmid, int len);
> struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
> 					      uint32_t hash, uint8_t *buf);
> +int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct
> +			       scsi_cmnd * cmd, union lpfc_vmid_io_tag *tag);
> void lpfc_vmid_vport_cleanup(struct lpfc_vport *vport);
> int lpfc_issue_els_qfpa(struct lpfc_vport *vport);
> 
> diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
> index 1d134a01ff3e..70d0a4d3d92e 100644
> --- a/drivers/scsi/lpfc/lpfc_scsi.c
> +++ b/drivers/scsi/lpfc/lpfc_scsi.c
> @@ -87,14 +87,6 @@ static void
> lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *psb);
> static int
> lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc);
> -static void
> -lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash,
> -			   struct lpfc_vmid *vmp);
> -static void lpfc_vmid_update_entry(struct lpfc_vport *vport, struct scsi_cmnd
> -				   *cmd, struct lpfc_vmid *vmp,
> -				   union lpfc_vmid_io_tag *tag);
> -static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport,
> -				    struct lpfc_vmid *vmid);
> 
> /**
>  * lpfc_sli4_set_rsp_sgl_last - Set the last bit in the response sge.
> @@ -5270,254 +5262,6 @@ void lpfc_poll_timeout(struct timer_list *t)
> 	}
> }
> 
> -/*
> - * lpfc_get_vmid_from_hashtable - search the UUID in the hash table
> - * @vport: The virtual port for which this call is being executed.
> - * @hash: calculated hash value
> - * @buf: uuid associated with the VE
> - * Return the VMID entry associated with the UUID
> - * Make sure to acquire the appropriate lock before invoking this routine.
> - */
> -struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
> -					      u32 hash, u8 *buf)
> -{
> -	struct lpfc_vmid *vmp;
> -
> -	hash_for_each_possible(vport->hash_table, vmp, hnode, hash) {
> -		if (memcmp(&vmp->host_vmid[0], buf, 16) == 0)
> -			return vmp;
> -	}
> -	return NULL;
> -}
> -
> -/*
> - * lpfc_put_vmid_in_hashtable - put the VMID in the hash table
> - * @vport: The virtual port for which this call is being executed.
> - * @hash - calculated hash value
> - * @vmp: Pointer to a VMID entry representing a VM sending I/O
> - *
> - * This routine will insert the newly acquired VMID entity in the hash table.
> - * Make sure to acquire the appropriate lock before invoking this routine.
> - */
> -static void
> -lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash,
> -			   struct lpfc_vmid *vmp)
> -{
> -	hash_add(vport->hash_table, &vmp->hnode, hash);
> -}
> -
> -/*
> - * lpfc_vmid_hash_fn - create a hash value of the UUID
> - * @vmid: uuid associated with the VE
> - * @len: length of the VMID string
> - * Returns the calculated hash value
> - */
> -int lpfc_vmid_hash_fn(const char *vmid, int len)
> -{
> -	int c;
> -	int hash = 0;
> -
> -	if (len == 0)
> -		return 0;
> -	while (len--) {
> -		c = *vmid++;
> -		if (c >= 'A' && c <= 'Z')
> -			c += 'a' - 'A';
> -
> -		hash = (hash + (c << LPFC_VMID_HASH_SHIFT) +
> -			(c >> LPFC_VMID_HASH_SHIFT)) * 19;
> -	}
> -
> -	return hash & LPFC_VMID_HASH_MASK;
> -}
> -
> -/*
> - * lpfc_vmid_update_entry - update the vmid entry in the hash table
> - * @vport: The virtual port for which this call is being executed.
> - * @cmd: address of scsi cmd descriptor
> - * @vmp: Pointer to a VMID entry representing a VM sending I/O
> - * @tag: VMID tag
> - */
> -static void lpfc_vmid_update_entry(struct lpfc_vport *vport, struct scsi_cmnd
> -				   *cmd, struct lpfc_vmid *vmp,
> -				   union lpfc_vmid_io_tag *tag)
> -{
> -	u64 *lta;
> -
> -	if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
> -		tag->cs_ctl_vmid = vmp->un.cs_ctl_vmid;
> -	else if (vport->phba->cfg_vmid_app_header)
> -		tag->app_id = vmp->un.app_id;
> -
> -	if (cmd->sc_data_direction == DMA_TO_DEVICE)
> -		vmp->io_wr_cnt++;
> -	else
> -		vmp->io_rd_cnt++;
> -
> -	/* update the last access timestamp in the table */
> -	lta = per_cpu_ptr(vmp->last_io_time, raw_smp_processor_id());
> -	*lta = jiffies;
> -}
> -
> -static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport,
> -				    struct lpfc_vmid *vmid)
> -{
> -	u32 hash;
> -	struct lpfc_vmid *pvmid;
> -
> -	if (vport->port_type == LPFC_PHYSICAL_PORT) {
> -		vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
> -	} else {
> -		hash = lpfc_vmid_hash_fn(vmid->host_vmid, vmid->vmid_len);
> -		pvmid =
> -		    lpfc_get_vmid_from_hashtable(vport->phba->pport, hash,
> -						vmid->host_vmid);
> -		if (pvmid)
> -			vmid->un.cs_ctl_vmid = pvmid->un.cs_ctl_vmid;
> -		else
> -			vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
> -	}
> -}
> -
> -/*
> - * lpfc_vmid_get_appid - get the VMID associated with the UUID
> - * @vport: The virtual port for which this call is being executed.
> - * @uuid: UUID associated with the VE
> - * @cmd: address of scsi_cmd descriptor
> - * @tag: VMID tag
> - * Returns status of the function
> - */
> -static int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct
> -			       scsi_cmnd * cmd, union lpfc_vmid_io_tag *tag)
> -{
> -	struct lpfc_vmid *vmp = NULL;
> -	int hash, len, rc = -EPERM, i;
> -
> -	/* check if QFPA is complete */
> -	if (lpfc_vmid_is_type_priority_tag(vport) &&
> -	    !(vport->vmid_flag & LPFC_VMID_QFPA_CMPL) &&
> -	    (vport->vmid_flag & LPFC_VMID_ISSUE_QFPA)) {
> -		vport->work_port_events |= WORKER_CHECK_VMID_ISSUE_QFPA;
> -		return -EAGAIN;
> -	}
> -
> -	/* search if the UUID has already been mapped to the VMID */
> -	len = strlen(uuid);
> -	hash = lpfc_vmid_hash_fn(uuid, len);
> -
> -	/* search for the VMID in the table */
> -	read_lock(&vport->vmid_lock);
> -	vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
> -
> -	/* if found, check if its already registered  */
> -	if (vmp  && vmp->flag & LPFC_VMID_REGISTERED) {
> -		read_unlock(&vport->vmid_lock);
> -		lpfc_vmid_update_entry(vport, cmd, vmp, tag);
> -		rc = 0;
> -	} else if (vmp && (vmp->flag & LPFC_VMID_REQ_REGISTER ||
> -			   vmp->flag & LPFC_VMID_DE_REGISTER)) {
> -		/* else if register or dereg request has already been sent */
> -		/* Hence VMID tag will not be added for this I/O */
> -		read_unlock(&vport->vmid_lock);
> -		rc = -EBUSY;
> -	} else {
> -		/* The VMID was not found in the hashtable. At this point, */
> -		/* drop the read lock first before proceeding further */
> -		read_unlock(&vport->vmid_lock);
> -		/* start the process to obtain one as per the */
> -		/* type of the VMID indicated */
> -		write_lock(&vport->vmid_lock);
> -		vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
> -
> -		/* while the read lock was released, in case the entry was */
> -		/* added by other context or is in process of being added */
> -		if (vmp && vmp->flag & LPFC_VMID_REGISTERED) {
> -			lpfc_vmid_update_entry(vport, cmd, vmp, tag);
> -			write_unlock(&vport->vmid_lock);
> -			return 0;
> -		} else if (vmp && vmp->flag & LPFC_VMID_REQ_REGISTER) {
> -			write_unlock(&vport->vmid_lock);
> -			return -EBUSY;
> -		}
> -
> -		/* else search and allocate a free slot in the hash table */
> -		if (vport->cur_vmid_cnt < vport->max_vmid) {
> -			for (i = 0; i < vport->max_vmid; i++) {
> -				vmp = vport->vmid + i;
> -				if (vmp->flag == LPFC_VMID_SLOT_FREE)
> -					break;
> -			}
> -			if (i == vport->max_vmid)
> -				vmp = NULL;
> -		} else {
> -			vmp = NULL;
> -		}
> -
> -		if (!vmp) {
> -			write_unlock(&vport->vmid_lock);
> -			return -ENOMEM;
> -		}
> -
> -		/* Add the vmid and register */
> -		lpfc_put_vmid_in_hashtable(vport, hash, vmp);
> -		vmp->vmid_len = len;
> -		memcpy(vmp->host_vmid, uuid, vmp->vmid_len);
> -		vmp->io_rd_cnt = 0;
> -		vmp->io_wr_cnt = 0;
> -		vmp->flag = LPFC_VMID_SLOT_USED;
> -
> -		vmp->delete_inactive =
> -			vport->vmid_inactivity_timeout ? 1 : 0;
> -
> -		/* if type priority tag, get next available VMID */
> -		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
> -			lpfc_vmid_assign_cs_ctl(vport, vmp);
> -
> -		/* allocate the per cpu variable for holding */
> -		/* the last access time stamp only if VMID is enabled */
> -		if (!vmp->last_io_time)
> -			vmp->last_io_time = __alloc_percpu(sizeof(u64),
> -							   __alignof__(struct
> -							   lpfc_vmid));
> -		if (!vmp->last_io_time) {
> -			hash_del(&vmp->hnode);
> -			vmp->flag = LPFC_VMID_SLOT_FREE;
> -			write_unlock(&vport->vmid_lock);
> -			return -EIO;
> -		}
> -
> -		write_unlock(&vport->vmid_lock);
> -
> -		/* complete transaction with switch */
> -		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
> -			rc = lpfc_vmid_uvem(vport, vmp, true);
> -		else if (vport->phba->cfg_vmid_app_header)
> -			rc = lpfc_vmid_cmd(vport, SLI_CTAS_RAPP_IDENT, vmp);
> -		if (!rc) {
> -			write_lock(&vport->vmid_lock);
> -			vport->cur_vmid_cnt++;
> -			vmp->flag |= LPFC_VMID_REQ_REGISTER;
> -			write_unlock(&vport->vmid_lock);
> -		} else {
> -			write_lock(&vport->vmid_lock);
> -			hash_del(&vmp->hnode);
> -			vmp->flag = LPFC_VMID_SLOT_FREE;
> -			free_percpu(vmp->last_io_time);
> -			write_unlock(&vport->vmid_lock);
> -			return -EIO;
> -		}
> -
> -		/* finally, enable the idle timer once */
> -		if (!(vport->phba->pport->vmid_flag & LPFC_VMID_TIMER_ENBLD)) {
> -			mod_timer(&vport->phba->inactive_vmid_poll,
> -				  jiffies +
> -				  msecs_to_jiffies(1000 * LPFC_VMID_TIMER));
> -			vport->phba->pport->vmid_flag |= LPFC_VMID_TIMER_ENBLD;
> -		}
> -	}
> -	return rc;
> -}
> -
> /*
>  * lpfc_is_command_vm_io - get the UUID from blk cgroup
>  * @cmd: Pointer to scsi_cmnd data structure
> diff --git a/drivers/scsi/lpfc/lpfc_vmid.c b/drivers/scsi/lpfc/lpfc_vmid.c
> new file mode 100644
> index 000000000000..f64ced04b912
> --- /dev/null
> +++ b/drivers/scsi/lpfc/lpfc_vmid.c
> @@ -0,0 +1,288 @@
> +/*******************************************************************
> + * This file is part of the Emulex Linux Device Driver for         *
> + * Fibre Channel Host Bus Adapters.                                *
> + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
> + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
> + * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
> + * EMULEX and SLI are trademarks of Emulex.                        *
> + * www.broadcom.com                                                *
> + * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
> + *                                                                 *
> + * This program is free software; you can redistribute it and/or   *
> + * modify it under the terms of version 2 of the GNU General       *
> + * Public License as published by the Free Software Foundation.    *
> + * This program is distributed in the hope that it will be useful. *
> + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
> + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
> + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
> + * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
> + * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
> + * more details, a copy of which can be found in the file COPYING  *
> + * included with this package.                                     *
> + *******************************************************************/
> +
> +#include <linux/interrupt.h>
> +#include <linux/dma-direction.h>
> +
> +#include <scsi/scsi_transport_fc.h>
> +
> +#include "lpfc_hw4.h"
> +#include "lpfc_hw.h"
> +#include "lpfc_sli.h"
> +#include "lpfc_sli4.h"
> +#include "lpfc_nl.h"
> +#include "lpfc_disc.h"
> +#include "lpfc.h"
> +#include "lpfc_crtn.h"
> +
> +
> +/*
> + * lpfc_get_vmid_from_hashtable - search the UUID in the hash table
> + * @vport: The virtual port for which this call is being executed.
> + * @hash: calculated hash value
> + * @buf: uuid associated with the VE
> + * Return the VMID entry associated with the UUID
> + * Make sure to acquire the appropriate lock before invoking this routine.
> + */
> +struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
> +					       u32 hash, u8 *buf)
> +{
> +	struct lpfc_vmid *vmp;
> +
> +	hash_for_each_possible(vport->hash_table, vmp, hnode, hash) {
> +		if (memcmp(&vmp->host_vmid[0], buf, 16) == 0)
> +			return vmp;
> +	}
> +	return NULL;
> +}
> +
> +/*
> + * lpfc_put_vmid_in_hashtable - put the VMID in the hash table
> + * @vport: The virtual port for which this call is being executed.
> + * @hash - calculated hash value
> + * @vmp: Pointer to a VMID entry representing a VM sending I/O
> + *
> + * This routine will insert the newly acquired VMID entity in the hash table.
> + * Make sure to acquire the appropriate lock before invoking this routine.
> + */
> +static void
> +lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash,
> +			   struct lpfc_vmid *vmp)
> +{
> +	hash_add(vport->hash_table, &vmp->hnode, hash);
> +}
> +
> +/*
> + * lpfc_vmid_hash_fn - create a hash value of the UUID
> + * @vmid: uuid associated with the VE
> + * @len: length of the VMID string
> + * Returns the calculated hash value
> + */
> +int lpfc_vmid_hash_fn(const char *vmid, int len)
> +{
> +	int c;
> +	int hash = 0;
> +
> +	if (len == 0)
> +		return 0;
> +	while (len--) {
> +		c = *vmid++;
> +		if (c >= 'A' && c <= 'Z')
> +			c += 'a' - 'A';
> +
> +		hash = (hash + (c << LPFC_VMID_HASH_SHIFT) +
> +			(c >> LPFC_VMID_HASH_SHIFT)) * 19;
> +	}
> +
> +	return hash & LPFC_VMID_HASH_MASK;
> +}
> +
> +/*
> + * lpfc_vmid_update_entry - update the vmid entry in the hash table
> + * @vport: The virtual port for which this call is being executed.
> + * @iodir: io direction
> + * @vmp: Pointer to a VMID entry representing a VM sending I/O
> + * @tag: VMID tag
> + */
> +static void lpfc_vmid_update_entry(struct lpfc_vport *vport,
> +				   enum dma_data_direction iodir,
> +				   struct lpfc_vmid *vmp,
> +				   union lpfc_vmid_io_tag *tag)
> +{
> +	u64 *lta;
> +
> +	if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
> +		tag->cs_ctl_vmid = vmp->un.cs_ctl_vmid;
> +	else if (vport->phba->cfg_vmid_app_header)
> +		tag->app_id = vmp->un.app_id;
> +
> +	if (iodir == DMA_TO_DEVICE)
> +		vmp->io_wr_cnt++;
> +	else if (iodir == DMA_FROM_DEVICE)
> +		vmp->io_rd_cnt++;
> +
> +	/* update the last access timestamp in the table */
> +	lta = per_cpu_ptr(vmp->last_io_time, raw_smp_processor_id());
> +	*lta = jiffies;
> +}
> +
> +static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport,
> +				    struct lpfc_vmid *vmid)
> +{
> +	u32 hash;
> +	struct lpfc_vmid *pvmid;
> +
> +	if (vport->port_type == LPFC_PHYSICAL_PORT) {
> +		vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
> +	} else {
> +		hash = lpfc_vmid_hash_fn(vmid->host_vmid, vmid->vmid_len);
> +		pvmid =
> +		    lpfc_get_vmid_from_hashtable(vport->phba->pport, hash,
> +						 vmid->host_vmid);
> +		if (pvmid)
> +			vmid->un.cs_ctl_vmid = pvmid->un.cs_ctl_vmid;
> +		else
> +			vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
> +	}
> +}
> +
> +/*
> + * lpfc_vmid_get_appid - get the VMID associated with the UUID
> + * @vport: The virtual port for which this call is being executed.
> + * @uuid: UUID associated with the VE
> + * @cmd: address of scsi_cmd descriptor
> + * @iodir: io direction
> + * @tag: VMID tag
> + * Returns status of the function
> + */
> +int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid,
> +			enum dma_data_direction iodir,
> +			union lpfc_vmid_io_tag *tag)
> +{
> +	struct lpfc_vmid *vmp = NULL;
> +	int hash, len, rc = -EPERM, i;
> +
> +	/* check if QFPA is complete */
> +	if (lpfc_vmid_is_type_priority_tag(vport) &&
> +	    !(vport->vmid_flag & LPFC_VMID_QFPA_CMPL) &&
> +	    (vport->vmid_flag & LPFC_VMID_ISSUE_QFPA)) {
> +		vport->work_port_events |= WORKER_CHECK_VMID_ISSUE_QFPA;
> +		return -EAGAIN;
> +	}
> +
> +	/* search if the UUID has already been mapped to the VMID */
> +	len = strlen(uuid);
> +	hash = lpfc_vmid_hash_fn(uuid, len);
> +
> +	/* search for the VMID in the table */
> +	read_lock(&vport->vmid_lock);
> +	vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
> +
> +	/* if found, check if its already registered  */
> +	if (vmp  && vmp->flag & LPFC_VMID_REGISTERED) {
> +		read_unlock(&vport->vmid_lock);
> +		lpfc_vmid_update_entry(vport, iodir, vmp, tag);
> +		rc = 0;
> +	} else if (vmp && (vmp->flag & LPFC_VMID_REQ_REGISTER ||
> +			   vmp->flag & LPFC_VMID_DE_REGISTER)) {
> +		/* else if register or dereg request has already been sent */
> +		/* Hence VMID tag will not be added for this I/O */
> +		read_unlock(&vport->vmid_lock);
> +		rc = -EBUSY;
> +	} else {
> +		/* The VMID was not found in the hashtable. At this point, */
> +		/* drop the read lock first before proceeding further */
> +		read_unlock(&vport->vmid_lock);
> +		/* start the process to obtain one as per the */
> +		/* type of the VMID indicated */
> +		write_lock(&vport->vmid_lock);
> +		vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
> +
> +		/* while the read lock was released, in case the entry was */
> +		/* added by other context or is in process of being added */
> +		if (vmp && vmp->flag & LPFC_VMID_REGISTERED) {
> +			lpfc_vmid_update_entry(vport, iodir, vmp, tag);
> +			write_unlock(&vport->vmid_lock);
> +			return 0;
> +		} else if (vmp && vmp->flag & LPFC_VMID_REQ_REGISTER) {
> +			write_unlock(&vport->vmid_lock);
> +			return -EBUSY;
> +		}
> +
> +		/* else search and allocate a free slot in the hash table */
> +		if (vport->cur_vmid_cnt < vport->max_vmid) {
> +			for (i = 0; i < vport->max_vmid; i++) {
> +				vmp = vport->vmid + i;
> +				if (vmp->flag == LPFC_VMID_SLOT_FREE)
> +					break;
> +			}
> +			if (i == vport->max_vmid)
> +				vmp = NULL;
> +		} else {
> +			vmp = NULL;
> +		}
> +
> +		if (!vmp) {
> +			write_unlock(&vport->vmid_lock);
> +			return -ENOMEM;
> +		}
> +
> +		/* Add the vmid and register */
> +		lpfc_put_vmid_in_hashtable(vport, hash, vmp);
> +		vmp->vmid_len = len;
> +		memcpy(vmp->host_vmid, uuid, vmp->vmid_len);
> +		vmp->io_rd_cnt = 0;
> +		vmp->io_wr_cnt = 0;
> +		vmp->flag = LPFC_VMID_SLOT_USED;
> +
> +		vmp->delete_inactive =
> +			vport->vmid_inactivity_timeout ? 1 : 0;
> +
> +		/* if type priority tag, get next available VMID */
> +		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
> +			lpfc_vmid_assign_cs_ctl(vport, vmp);
> +
> +		/* allocate the per cpu variable for holding */
> +		/* the last access time stamp only if VMID is enabled */
> +		if (!vmp->last_io_time)
> +			vmp->last_io_time = __alloc_percpu(sizeof(u64),
> +							   __alignof__(struct
> +							   lpfc_vmid));
> +		if (!vmp->last_io_time) {
> +			hash_del(&vmp->hnode);
> +			vmp->flag = LPFC_VMID_SLOT_FREE;
> +			write_unlock(&vport->vmid_lock);
> +			return -EIO;
> +		}
> +
> +		write_unlock(&vport->vmid_lock);
> +
> +		/* complete transaction with switch */
> +		if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
> +			rc = lpfc_vmid_uvem(vport, vmp, true);
> +		else if (vport->phba->cfg_vmid_app_header)
> +			rc = lpfc_vmid_cmd(vport, SLI_CTAS_RAPP_IDENT, vmp);
> +		if (!rc) {
> +			write_lock(&vport->vmid_lock);
> +			vport->cur_vmid_cnt++;
> +			vmp->flag |= LPFC_VMID_REQ_REGISTER;
> +			write_unlock(&vport->vmid_lock);
> +		} else {
> +			write_lock(&vport->vmid_lock);
> +			hash_del(&vmp->hnode);
> +			vmp->flag = LPFC_VMID_SLOT_FREE;
> +			free_percpu(vmp->last_io_time);
> +			write_unlock(&vport->vmid_lock);
> +			return -EIO;
> +		}
> +
> +		/* finally, enable the idle timer once */
> +		if (!(vport->phba->pport->vmid_flag & LPFC_VMID_TIMER_ENBLD)) {
> +			mod_timer(&vport->phba->inactive_vmid_poll,
> +				  jiffies +
> +				  msecs_to_jiffies(1000 * LPFC_VMID_TIMER));
> +			vport->phba->pport->vmid_flag |= LPFC_VMID_TIMER_ENBLD;
> +		}
> +	}
> +	return rc;
> +}
> -- 
> 2.26.2
> 

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>

--
Himanshu Madhani	Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent
  2022-05-10 20:00 ` [PATCH 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent James Smart
  2022-05-12  9:51   ` Hannes Reinecke
@ 2022-05-12 23:48   ` Himanshu Madhani
  1 sibling, 0 replies; 15+ messages in thread
From: Himanshu Madhani @ 2022-05-12 23:48 UTC (permalink / raw)
  To: James Smart; +Cc: linux-scsi, linux-nvme, Gaurav Srivastava



> On May 10, 2022, at 1:00 PM, James Smart <jsmart2021@gmail.com> wrote:
> 
> Rework lpfc_vmid_get_appid() arguments to remove scsi cmd dependency.
> It's now callable by nvme path.
> 
> Fixup scsi calling path for arg change.
> 
> Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
> drivers/scsi/lpfc/lpfc_crtn.h | 5 +++--
> drivers/scsi/lpfc/lpfc_scsi.c | 7 ++++---
> 2 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
> index 913844f01bf5..b1be0dd0337a 100644
> --- a/drivers/scsi/lpfc/lpfc_crtn.h
> +++ b/drivers/scsi/lpfc/lpfc_crtn.h
> @@ -671,8 +671,9 @@ int lpfc_vmid_cmd(struct lpfc_vport *vport,
> int lpfc_vmid_hash_fn(const char *vmid, int len);
> struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
> 					      uint32_t hash, uint8_t *buf);
> -int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct
> -			       scsi_cmnd * cmd, union lpfc_vmid_io_tag *tag);
> +int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid,
> +			enum dma_data_direction iodir,
> +			union lpfc_vmid_io_tag *tag);
> void lpfc_vmid_vport_cleanup(struct lpfc_vport *vport);
> int lpfc_issue_els_qfpa(struct lpfc_vport *vport);
> 
> diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
> index 70d0a4d3d92e..f5f4409e24cd 100644
> --- a/drivers/scsi/lpfc/lpfc_scsi.c
> +++ b/drivers/scsi/lpfc/lpfc_scsi.c
> @@ -5446,9 +5446,10 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
> 		uuid = lpfc_is_command_vm_io(cmnd);
> 
> 		if (uuid) {
> -			err = lpfc_vmid_get_appid(vport, uuid, cmnd,
> -				(union lpfc_vmid_io_tag *)
> -					&cur_iocbq->vmid_tag);
> +			err = lpfc_vmid_get_appid(vport, uuid,
> +					cmnd->sc_data_direction,
> +					(union lpfc_vmid_io_tag *)
> +						&cur_iocbq->vmid_tag);
> 			if (!err)
> 				cur_iocbq->cmd_flag |= LPFC_IO_VMID;
> 		}
> -- 
> 2.26.2
> 

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>

--
Himanshu Madhani	Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/4] lpfc: Add support for vmid tagging of NVMe I/Os
  2022-05-10 20:00 ` [PATCH 4/4] lpfc: Add support for vmid tagging of NVMe I/Os James Smart
  2022-05-12  9:51   ` Hannes Reinecke
@ 2022-05-12 23:50   ` Himanshu Madhani
  1 sibling, 0 replies; 15+ messages in thread
From: Himanshu Madhani @ 2022-05-12 23:50 UTC (permalink / raw)
  To: James Smart; +Cc: linux-scsi, linux-nvme, Gaurav Srivastava



> On May 10, 2022, at 1:00 PM, James Smart <jsmart2021@gmail.com> wrote:
> 
> Modify the nvme io path to look for vmid support and call the
> transport to obtain the io's appid value.
> 
> Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
> drivers/scsi/lpfc/lpfc_nvme.c | 45 +++++++++++++++++++++++++++++++++++
> 1 file changed, 45 insertions(+)
> 
> diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
> index 5385f4de5523..335e90633933 100644
> --- a/drivers/scsi/lpfc/lpfc_nvme.c
> +++ b/drivers/scsi/lpfc/lpfc_nvme.c
> @@ -1279,6 +1279,19 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
> 
> 	/* Words 13 14 15 are for PBDE support */
> 
> +	/* add the VMID tags as per switch response */
> +	if (unlikely(lpfc_ncmd->cur_iocbq.cmd_flag & LPFC_IO_VMID)) {
> +		if (phba->pport->vmid_priority_tagging) {
> +			bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1);
> +			bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com,
> +			       lpfc_ncmd->cur_iocbq.vmid_tag.cs_ctl_vmid);
> +		} else {
> +			bf_set(wqe_appid, &wqe->fcp_iwrite.wqe_com, 1);
> +			bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1);
> +			wqe->words[31] = lpfc_ncmd->cur_iocbq.vmid_tag.app_id;
> +		}
> +	}
> +
> 	pwqeq->vport = vport;
> 	return 0;
> }
> @@ -1504,6 +1517,11 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
> 	struct lpfc_nvme_fcpreq_priv *freqpriv;
> 	struct nvme_common_command *sqe;
> 	uint64_t start = 0;
> +#if (IS_ENABLED(CONFIG_NVME_FC))
> +	u8 *uuid = NULL;
> +	int err;
> +	enum dma_data_direction iodir;
> +#endif
> 
> 	/* Validate pointers. LLDD fault handling with transport does
> 	 * have timing races.
> @@ -1662,6 +1680,33 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
> 	lpfc_ncmd->ndlp = ndlp;
> 	lpfc_ncmd->qidx = lpfc_queue_info->qidx;
> 
> +#if (IS_ENABLED(CONFIG_NVME_FC))
> +	/* check the necessary and sufficient condition to support VMID */
> +	if (lpfc_is_vmid_enabled(phba) &&
> +	    (ndlp->vmid_support ||
> +	     phba->pport->vmid_priority_tagging ==
> +	     LPFC_VMID_PRIO_TAG_ALL_TARGETS)) {
> +		/* is the I/O generated by a VM, get the associated virtual */
> +		/* entity id */
> +		uuid = nvme_fc_io_getuuid(pnvme_fcreq);
> +
> +		if (uuid) {
> +			if (pnvme_fcreq->io_dir == NVMEFC_FCP_WRITE)
> +				iodir = DMA_TO_DEVICE;
> +			else if (pnvme_fcreq->io_dir == NVMEFC_FCP_READ)
> +				iodir = DMA_FROM_DEVICE;
> +			else
> +				iodir = DMA_NONE;
> +
> +			err = lpfc_vmid_get_appid(vport, uuid, iodir,
> +					(union lpfc_vmid_io_tag *)
> +						&lpfc_ncmd->cur_iocbq.vmid_tag);
> +			if (!err)
> +				lpfc_ncmd->cur_iocbq.cmd_flag |= LPFC_IO_VMID;
> +		}
> +	}
> +#endif
> +
> 	/*
> 	 * Issue the IO on the WQ indicated by index in the hw_queue_handle.
> 	 * This identfier was create in our hardware queue create callback
> -- 
> 2.26.2
> 

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>

--
Himanshu Madhani	Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid
  2022-05-10 20:00 ` [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
  2022-05-12  9:50   ` Hannes Reinecke
  2022-05-12 23:38   ` Himanshu Madhani
@ 2022-05-16  5:57   ` Christoph Hellwig
  2 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2022-05-16  5:57 UTC (permalink / raw)
  To: James Smart; +Cc: linux-scsi, linux-nvme, Muneendra

On Tue, May 10, 2022 at 01:00:25PM -0700, James Smart wrote:
> From: Muneendra <muneendra.kumar@broadcom.com>
> 
> Add nvme_fc_io_getuuid() to the nvme-fc transport.
> The routine is invoked by the fc LLDD on a per-io request basis.
> The routine translates from the fc-specific request structure to
> the bio and the cgroup structure in order to obtain the fc appid
> stored in the cgroup structure. If a value is not set or a bio
> is not found, a NULL appid (aka uuid) will be returned to the LLDD.
> 
> Signed-off-by: Muneendra <muneendra.kumar@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>

I'm fine with picking this up through the scsi tree:

Acked-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver
  2022-05-10 20:00 [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
                   ` (3 preceding siblings ...)
  2022-05-10 20:00 ` [PATCH 4/4] lpfc: Add support for vmid tagging of NVMe I/Os James Smart
@ 2022-05-17  1:40 ` Martin K. Petersen
  4 siblings, 0 replies; 15+ messages in thread
From: Martin K. Petersen @ 2022-05-17  1:40 UTC (permalink / raw)
  To: James Smart; +Cc: linux-scsi, linux-nvme


James,

> This patch adds vmid support to the nvme-fc transport.

Applied to 5.19/scsi-staging, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2022-05-17  1:40 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-10 20:00 [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
2022-05-10 20:00 ` [PATCH 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
2022-05-12  9:50   ` Hannes Reinecke
2022-05-12 23:38   ` Himanshu Madhani
2022-05-16  5:57   ` Christoph Hellwig
2022-05-10 20:00 ` [PATCH 2/4] lpfc: commonize VMID code location James Smart
2022-05-12  9:50   ` Hannes Reinecke
2022-05-12 23:45   ` Himanshu Madhani
2022-05-10 20:00 ` [PATCH 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent James Smart
2022-05-12  9:51   ` Hannes Reinecke
2022-05-12 23:48   ` Himanshu Madhani
2022-05-10 20:00 ` [PATCH 4/4] lpfc: Add support for vmid tagging of NVMe I/Os James Smart
2022-05-12  9:51   ` Hannes Reinecke
2022-05-12 23:50   ` Himanshu Madhani
2022-05-17  1:40 ` [PATCH 0/4] Add VMID support to nvme-fc transport and lpfc driver Martin K. Petersen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.