scsi: lpfc: vmid: Implement CT commands for appid
authorGaurav Srivastava <gaurav.srivastava@broadcom.com>
Tue, 8 Jun 2021 04:35:52 +0000 (10:05 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 10 Jun 2021 14:01:33 +0000 (10:01 -0400)
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: Hannes Reinecke <hare@suse.de>
Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Muneendra Kumar <muneendra.kumar@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_ct.c

index cbf1be5..610b6da 100644 (file)
@@ -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;
+}