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

scsi: lpfc: vmid: Implement CT commands for appid

Implement CT commands for registering and deregistering the appid for the
application. Also, a small change in decrementing the ndlp ref counter has
been added.

Link: https://lore.kernel.org/r/20210608043556.274139-10-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 dc50715e
Loading
Loading
Loading
Loading
+255 −0
Original line number Diff line number Diff line
@@ -75,6 +75,9 @@


static char *lpfc_release_version = LPFC_DRIVER_VERSION;
static void
lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
		      struct lpfc_iocbq *rspiocb);

static void
lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
@@ -3777,3 +3780,255 @@ lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
	}
	return;
}

static void
lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
		      struct lpfc_iocbq *rspiocb)
{
	struct lpfc_vport *vport = cmdiocb->vport;
	struct lpfc_dmabuf *inp = cmdiocb->context1;
	struct lpfc_dmabuf *outp = cmdiocb->context2;
	struct lpfc_sli_ct_request *ctcmd = inp->virt;
	struct lpfc_sli_ct_request *ctrsp = outp->virt;
	u16 rsp = ctrsp->CommandResponse.bits.CmdRsp;
	struct app_id_object *app;
	u32 cmd, hash, bucket;
	struct lpfc_vmid *vmp, *cur;
	u8 *data = outp->virt;
	int i;

	cmd = be16_to_cpu(ctcmd->CommandResponse.bits.CmdRsp);
	if (cmd == SLI_CTAS_DALLAPP_ID)
		lpfc_ct_free_iocb(phba, cmdiocb);

	if (lpfc_els_chk_latt(vport) || rspiocb->iocb.ulpStatus) {
		if (cmd != SLI_CTAS_DALLAPP_ID)
			return;
	}
	/* Check for a CT LS_RJT response */
	if (rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
		if (cmd != SLI_CTAS_DALLAPP_ID)
			lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
					 "3306 VMID FS_RJT Data: x%x x%x x%x\n",
					 cmd, ctrsp->ReasonCode,
					 ctrsp->Explanation);
		if ((cmd != SLI_CTAS_DALLAPP_ID) ||
		    (ctrsp->ReasonCode != SLI_CT_UNABLE_TO_PERFORM_REQ) ||
		    (ctrsp->Explanation != SLI_CT_APP_ID_NOT_AVAILABLE)) {
			/* If DALLAPP_ID failed retry later */
			if (cmd == SLI_CTAS_DALLAPP_ID)
				vport->load_flag |= FC_DEREGISTER_ALL_APP_ID;
			return;
		}
	}

	switch (cmd) {
	case SLI_CTAS_RAPP_IDENT:
		app = (struct app_id_object *)(RAPP_IDENT_OFFSET + data);
		lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
				 "6712 RAPP_IDENT app id %d  port id x%x id "
				 "len %d\n", be32_to_cpu(app->app_id),
				 be32_to_cpu(app->port_id),
				 app->obj.entity_id_len);

		if (app->obj.entity_id_len == 0 || app->port_id == 0)
			return;

		hash = lpfc_vmid_hash_fn(app->obj.entity_id,
					 app->obj.entity_id_len);
		vmp = lpfc_get_vmid_from_hashtable(vport, hash,
						  app->obj.entity_id);
		if (vmp) {
			write_lock(&vport->vmid_lock);
			vmp->un.app_id = be32_to_cpu(app->app_id);
			vmp->flag |= LPFC_VMID_REGISTERED;
			vmp->flag &= ~LPFC_VMID_REQ_REGISTER;
			write_unlock(&vport->vmid_lock);
			/* Set IN USE flag */
			vport->vmid_flag |= LPFC_VMID_IN_USE;
		} else {
			lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
					 "6901 No entry found %s hash %d\n",
					 app->obj.entity_id, hash);
		}
		break;
	case SLI_CTAS_DAPP_IDENT:
		app = (struct app_id_object *)(DAPP_IDENT_OFFSET + data);
		lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
				 "6713 DAPP_IDENT app id %d  port id x%x\n",
				 be32_to_cpu(app->app_id),
				 be32_to_cpu(app->port_id));
		break;
	case SLI_CTAS_DALLAPP_ID:
		lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
				 "8856 Deregistered all app ids\n");
		read_lock(&vport->vmid_lock);
		for (i = 0; i < phba->cfg_max_vmid; i++) {
			vmp = &vport->vmid[i];
			if (vmp->flag != LPFC_VMID_SLOT_FREE)
				memset(vmp, 0, sizeof(struct lpfc_vmid));
		}
		read_unlock(&vport->vmid_lock);
		/* for all elements in the hash table */
		if (!hash_empty(vport->hash_table))
			hash_for_each(vport->hash_table, bucket, cur, hnode)
				hash_del(&cur->hnode);
		vport->load_flag |= FC_ALLOW_VMID;
		break;
	default:
		lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
				 "8857 Invalid command code\n");
	}
}

/**
 * lpfc_vmid_cmd - Build and send a FDMI cmd to the specified NPort
 * @vport: pointer to a host virtual N_Port data structure.
 * @ndlp: ndlp to send FDMI cmd to (if NULL use FDMI_DID)
 * cmdcode: FDMI command to send
 * mask: Mask of HBA or PORT Attributes to send
 *
 * Builds and sends a FDMI command using the CT subsystem.
 */
int
lpfc_vmid_cmd(struct lpfc_vport *vport,
	      int cmdcode, struct lpfc_vmid *vmid)
{
	struct lpfc_hba *phba = vport->phba;
	struct lpfc_dmabuf *mp, *bmp;
	struct lpfc_sli_ct_request *ctreq;
	struct ulp_bde64 *bpl;
	u32 size;
	u32 rsp_size;
	u8 *data;
	struct lpfc_vmid_rapp_ident_list *rap;
	struct lpfc_vmid_dapp_ident_list *dap;
	u8 retry = 0;
	struct lpfc_nodelist *ndlp;

	void (*cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
		     struct lpfc_iocbq *rspiocb);

	ndlp = lpfc_findnode_did(vport, FDMI_DID);
	if (!ndlp || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)
		return 0;

	cmpl = lpfc_cmpl_ct_cmd_vmid;

	/* fill in BDEs for command */
	/* Allocate buffer for command payload */
	mp = kmalloc(sizeof(*mp), GFP_KERNEL);
	if (!mp)
		goto vmid_free_mp_exit;

	mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
	if (!mp->virt)
		goto vmid_free_mp_virt_exit;

	/* Allocate buffer for Buffer ptr list */
	bmp = kmalloc(sizeof(*bmp), GFP_KERNEL);
	if (!bmp)
		goto vmid_free_bmp_exit;

	bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
	if (!bmp->virt)
		goto vmid_free_bmp_virt_exit;

	INIT_LIST_HEAD(&mp->list);
	INIT_LIST_HEAD(&bmp->list);

	lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
			 "3275 VMID Request Data: x%x x%x x%x\n",
			 vport->fc_flag, vport->port_state, cmdcode);
	ctreq = (struct lpfc_sli_ct_request *)mp->virt;
	data = mp->virt;
	/* First populate the CT_IU preamble */
	memset(data, 0, LPFC_BPL_SIZE);
	ctreq->RevisionId.bits.Revision = SLI_CT_REVISION;
	ctreq->RevisionId.bits.InId = 0;

	ctreq->FsType = SLI_CT_MANAGEMENT_SERVICE;
	ctreq->FsSubType = SLI_CT_APP_SEV_Subtypes;

	ctreq->CommandResponse.bits.CmdRsp = cpu_to_be16(cmdcode);
	rsp_size = LPFC_BPL_SIZE;
	size = 0;

	switch (cmdcode) {
	case SLI_CTAS_RAPP_IDENT:
		lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
				 "1329 RAPP_IDENT for %s\n", vmid->host_vmid);
		ctreq->un.PortID = cpu_to_be32(vport->fc_myDID);
		rap = (struct lpfc_vmid_rapp_ident_list *)
			(DAPP_IDENT_OFFSET + data);
		rap->no_of_objects = cpu_to_be32(1);
		rap->obj[0].entity_id_len = vmid->vmid_len;
		memcpy(rap->obj[0].entity_id, vmid->host_vmid, vmid->vmid_len);
		size = RAPP_IDENT_OFFSET +
			sizeof(struct lpfc_vmid_rapp_ident_list);
		retry = 1;
		break;

	case SLI_CTAS_GALLAPPIA_ID:
		ctreq->un.PortID = cpu_to_be32(vport->fc_myDID);
		size = GALLAPPIA_ID_SIZE;
		break;

	case SLI_CTAS_DAPP_IDENT:
		lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
				 "1469 DAPP_IDENT for %s\n", vmid->host_vmid);
		ctreq->un.PortID = cpu_to_be32(vport->fc_myDID);
		dap = (struct lpfc_vmid_dapp_ident_list *)
			(DAPP_IDENT_OFFSET + data);
		dap->no_of_objects = cpu_to_be32(1);
		dap->obj[0].entity_id_len = vmid->vmid_len;
		memcpy(dap->obj[0].entity_id, vmid->host_vmid, vmid->vmid_len);
		size = DAPP_IDENT_OFFSET +
			sizeof(struct lpfc_vmid_dapp_ident_list);
		write_lock(&vport->vmid_lock);
		vmid->flag &= ~LPFC_VMID_REGISTERED;
		write_unlock(&vport->vmid_lock);
		retry = 1;
		break;

	case SLI_CTAS_DALLAPP_ID:
		ctreq->un.PortID = cpu_to_be32(vport->fc_myDID);
		size = DALLAPP_ID_SIZE;
		break;

	default:
		lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
				 "7062 VMID cmdcode x%x not supported\n",
				 cmdcode);
		goto vmid_free_all_mem;
	}

	ctreq->CommandResponse.bits.Size = cpu_to_be16(rsp_size);

	bpl = (struct ulp_bde64 *)bmp->virt;
	bpl->addrHigh = putPaddrHigh(mp->phys);
	bpl->addrLow = putPaddrLow(mp->phys);
	bpl->tus.f.bdeFlags = 0;
	bpl->tus.f.bdeSize = size;

	/* The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count
	 * to hold ndlp reference for the corresponding callback function.
	 */
	if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry))
		return 0;

 vmid_free_all_mem:
	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
 vmid_free_bmp_virt_exit:
	kfree(bmp);
 vmid_free_bmp_exit:
	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 vmid_free_mp_virt_exit:
	kfree(mp);
 vmid_free_mp_exit:

	/* Issue CT request failed */
	lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY,
			 "3276 VMID CT request failed Data: x%x\n", cmdcode);
	return -EIO;
}