* [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver
@ 2022-05-19 12:31 James Smart
2022-05-19 12:31 ` [PATCH v2 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: James Smart @ 2022-05-19 12:31 UTC (permalink / raw)
To: linux-scsi; +Cc: 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.
V2:
Revised the first patch which calls blkcg_get_fc_appid().
Fixes build errors when merged with
blk-cgroup: move blkcg_{get,set}_fc_appid out of line
commit db05628435aa
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 | 18 +++
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, 373 insertions(+), 260 deletions(-)
create mode 100644 drivers/scsi/lpfc/lpfc_vmid.c
--
2.26.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid
2022-05-19 12:31 [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
@ 2022-05-19 12:31 ` James Smart
2022-05-19 12:31 ` [PATCH v2 2/4] lpfc: commonize VMID code location James Smart
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: James Smart @ 2022-05-19 12:31 UTC (permalink / raw)
To: linux-scsi
Cc: Muneendra, James Smart, Hannes Reinecke, Himanshu Madhani,
Christoph Hellwig
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 Kumar <muneendra.kumar@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Acked-by: Christoph Hellwig <hch@lst.de>
---
v2: modify to sync with Christoph's patch:
blk-cgroup: move blkcg_{get,set}_fc_appid out of line
commit db05628435aa
---
drivers/nvme/host/fc.c | 18 ++++++++++++++++++
include/linux/nvme-fc-driver.h | 14 ++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index 080f85f4105f..05f9da251758 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -1899,6 +1899,24 @@ 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;
+
+ if (!IS_ENABLED(CONFIG_BLK_CGROUP_FC_APPID) || !rq->bio)
+ return NULL;
+ return blkcg_get_fc_appid(rq->bio);
+}
+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] 7+ messages in thread
* [PATCH v2 2/4] lpfc: commonize VMID code location
2022-05-19 12:31 [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
2022-05-19 12:31 ` [PATCH v2 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
@ 2022-05-19 12:31 ` James Smart
2022-05-19 12:31 ` [PATCH v2 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent James Smart
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: James Smart @ 2022-05-19 12:31 UTC (permalink / raw)
To: linux-scsi
Cc: James Smart, Gaurav Srivastava, Hannes Reinecke, Himanshu Madhani
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>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.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] 7+ messages in thread
* [PATCH v2 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent
2022-05-19 12:31 [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
2022-05-19 12:31 ` [PATCH v2 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
2022-05-19 12:31 ` [PATCH v2 2/4] lpfc: commonize VMID code location James Smart
@ 2022-05-19 12:31 ` James Smart
2022-05-19 12:31 ` [PATCH v2 4/4] lpfc: Add support for vmid tagging of NVMe I/Os James Smart
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: James Smart @ 2022-05-19 12:31 UTC (permalink / raw)
To: linux-scsi
Cc: James Smart, Gaurav Srivastava, Hannes Reinecke, Himanshu Madhani
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>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.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] 7+ messages in thread
* [PATCH v2 4/4] lpfc: Add support for vmid tagging of NVMe I/Os
2022-05-19 12:31 [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
` (2 preceding siblings ...)
2022-05-19 12:31 ` [PATCH v2 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent James Smart
@ 2022-05-19 12:31 ` James Smart
2022-05-20 0:25 ` [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver Martin K. Petersen
2022-05-24 3:27 ` Martin K. Petersen
5 siblings, 0 replies; 7+ messages in thread
From: James Smart @ 2022-05-19 12:31 UTC (permalink / raw)
To: linux-scsi
Cc: James Smart, Gaurav Srivastava, Hannes Reinecke, Himanshu Madhani
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>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.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] 7+ messages in thread
* Re: [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver
2022-05-19 12:31 [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
` (3 preceding siblings ...)
2022-05-19 12:31 ` [PATCH v2 4/4] lpfc: Add support for vmid tagging of NVMe I/Os James Smart
@ 2022-05-20 0:25 ` Martin K. Petersen
2022-05-24 3:27 ` Martin K. Petersen
5 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2022-05-20 0:25 UTC (permalink / raw)
To: James Smart; +Cc: linux-scsi
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] 7+ messages in thread
* Re: [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver
2022-05-19 12:31 [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
` (4 preceding siblings ...)
2022-05-20 0:25 ` [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver Martin K. Petersen
@ 2022-05-24 3:27 ` Martin K. Petersen
5 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2022-05-24 3:27 UTC (permalink / raw)
To: linux-scsi, James Smart; +Cc: Martin K . Petersen
On Thu, 19 May 2022 05:31:06 -0700, James Smart wrote:
> 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.
>
> [...]
Applied to 5.19/scsi-queue, thanks!
[1/4] nvme-fc: Add new routine nvme_fc_io_getuuid
https://git.kernel.org/mkp/scsi/c/827fc630e4c8
[2/4] lpfc: commonize VMID code location
https://git.kernel.org/mkp/scsi/c/ed913cf4a533
[3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent
https://git.kernel.org/mkp/scsi/c/348efeca7487
[4/4] lpfc: Add support for vmid tagging of NVMe I/Os
https://git.kernel.org/mkp/scsi/c/896325a8b165
--
Martin K. Petersen Oracle Linux Engineering
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-05-24 3:27 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-05-19 12:31 [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver James Smart
2022-05-19 12:31 ` [PATCH v2 1/4] nvme-fc: Add new routine nvme_fc_io_getuuid James Smart
2022-05-19 12:31 ` [PATCH v2 2/4] lpfc: commonize VMID code location James Smart
2022-05-19 12:31 ` [PATCH v2 3/4] lpfc: rework lpfc_vmid_get_appid() to be protocol independent James Smart
2022-05-19 12:31 ` [PATCH v2 4/4] lpfc: Add support for vmid tagging of NVMe I/Os James Smart
2022-05-20 0:25 ` [PATCH v2 0/4] Add VMID support to nvme-fc transport and lpfc driver Martin K. Petersen
2022-05-24 3:27 ` Martin K. Petersen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).