Commit dc50715e authored by Gaurav Srivastava's avatar Gaurav Srivastava Committed by Martin K. Petersen
Browse files

scsi: lpfc: vmid: Functions to manage VMIDs

Implement routines to save, retrieve, and remove the VMIDs from the data
structure. A hash table is used to save the VMIDs and the corresponding
UUIDs associated with the application/VMs.

Link: https://lore.kernel.org/r/20210608043556.274139-9-muneendra.kumar@broadcom.com


Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarGaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMuneendra Kumar <muneendra.kumar@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7e473de7
Loading
Loading
Loading
Loading
+118 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <asm/unaligned.h>
#include <linux/t10-pi.h>
#include <linux/crc-t10dif.h>
#include <linux/blk-cgroup.h>
#include <net/checksum.h>

#include <scsi/scsi.h>
@@ -86,6 +87,14 @@ 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);

static inline unsigned
lpfc_cmd_blksize(struct scsi_cmnd *sc)
@@ -5160,6 +5169,115 @@ 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->vmid_priority_tagging)
		tag->cs_ctl_vmid = vmp->un.cs_ctl_vmid;
	else
		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_queuecommand - scsi_host_template queuecommand entry point
 * @shost: kernel scsi host pointer.