Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[pandora-kernel.git] / drivers / scsi / lpfc / lpfc_mbox.c
index e6ce903..83450cc 100644 (file)
@@ -610,7 +610,8 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
        mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
        mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
        mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys);
-       mb->un.varRdSparm.vpi = vpi + phba->vpi_base;
+       if (phba->sli_rev >= LPFC_SLI_REV3)
+               mb->un.varRdSparm.vpi = phba->vpi_ids[vpi];
 
        /* save address for completion */
        pmb->context1 = mp;
@@ -643,9 +644,10 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
        memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
        mb->un.varUnregDID.did = did;
-       if (vpi != 0xffff)
-               vpi += phba->vpi_base;
        mb->un.varUnregDID.vpi = vpi;
+       if ((vpi != 0xffff) &&
+           (phba->sli_rev == LPFC_SLI_REV4))
+               mb->un.varUnregDID.vpi = phba->vpi_ids[vpi];
 
        mb->mbxCommand = MBX_UNREG_D_ID;
        mb->mbxOwner = OWN_HOST;
@@ -738,12 +740,10 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
        memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
        mb->un.varRegLogin.rpi = 0;
-       if (phba->sli_rev == LPFC_SLI_REV4) {
-               mb->un.varRegLogin.rpi = rpi;
-               if (mb->un.varRegLogin.rpi == LPFC_RPI_ALLOC_ERROR)
-                       return 1;
-       }
-       mb->un.varRegLogin.vpi = vpi + phba->vpi_base;
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               mb->un.varRegLogin.rpi = phba->sli4_hba.rpi_ids[rpi];
+       if (phba->sli_rev >= LPFC_SLI_REV3)
+               mb->un.varRegLogin.vpi = phba->vpi_ids[vpi];
        mb->un.varRegLogin.did = did;
        mb->mbxOwner = OWN_HOST;
        /* Get a buffer to hold NPorts Service Parameters */
@@ -757,7 +757,7 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
                lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
                                "0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, "
                                "rpi x%x\n", vpi, did, rpi);
-               return (1);
+               return 1;
        }
        INIT_LIST_HEAD(&mp->list);
        sparam = mp->virt;
@@ -773,7 +773,7 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
        mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys);
        mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys);
 
-       return (0);
+       return 0;
 }
 
 /**
@@ -789,6 +789,9 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
  *
  * This routine prepares the mailbox command for unregistering remote port
  * login.
+ *
+ * For SLI4 ports, the rpi passed to this function must be the physical
+ * rpi value, not the logical index.
  **/
 void
 lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
@@ -799,9 +802,10 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
        mb = &pmb->u.mb;
        memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
-       mb->un.varUnregLogin.rpi = (uint16_t) rpi;
+       mb->un.varUnregLogin.rpi = rpi;
        mb->un.varUnregLogin.rsvd1 = 0;
-       mb->un.varUnregLogin.vpi = vpi + phba->vpi_base;
+       if (phba->sli_rev >= LPFC_SLI_REV3)
+               mb->un.varUnregLogin.vpi = phba->vpi_ids[vpi];
 
        mb->mbxCommand = MBX_UNREG_LOGIN;
        mb->mbxOwner = OWN_HOST;
@@ -825,9 +829,16 @@ lpfc_sli4_unreg_all_rpis(struct lpfc_vport *vport)
 
        mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (mbox) {
-               lpfc_unreg_login(phba, vport->vpi,
-                       vport->vpi + phba->vpi_base, mbox);
-               mbox->u.mb.un.varUnregLogin.rsvd1 = 0x4000 ;
+               /*
+                * For SLI4 functions, the rpi field is overloaded for
+                * the vport context unreg all.  This routine passes
+                * 0 for the rpi field in lpfc_unreg_login for compatibility
+                * with SLI3 and then overrides the rpi field with the
+                * expected value for SLI4.
+                */
+               lpfc_unreg_login(phba, vport->vpi, phba->vpi_ids[vport->vpi],
+                                mbox);
+               mbox->u.mb.un.varUnregLogin.rsvd1 = 0x4000;
                mbox->vport = vport;
                mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
                mbox->context1 = NULL;
@@ -865,9 +876,13 @@ lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb)
        if ((phba->sli_rev == LPFC_SLI_REV4) &&
                !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI))
                mb->un.varRegVpi.upd = 1;
-       mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base;
+
+       mb->un.varRegVpi.vpi = phba->vpi_ids[vport->vpi];
        mb->un.varRegVpi.sid = vport->fc_myDID;
-       mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base;
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               mb->un.varRegVpi.vfi = phba->sli4_hba.vfi_ids[vport->vfi];
+       else
+               mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base;
        memcpy(mb->un.varRegVpi.wwn, &vport->fc_portname,
               sizeof(struct lpfc_name));
        mb->un.varRegVpi.wwn[0] = cpu_to_le32(mb->un.varRegVpi.wwn[0]);
@@ -901,10 +916,10 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
        MAILBOX_t *mb = &pmb->u.mb;
        memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
-       if (phba->sli_rev < LPFC_SLI_REV4)
-               mb->un.varUnregVpi.vpi = vpi + phba->vpi_base;
-       else
-               mb->un.varUnregVpi.sli4_vpi = vpi + phba->vpi_base;
+       if (phba->sli_rev == LPFC_SLI_REV3)
+               mb->un.varUnregVpi.vpi = phba->vpi_ids[vpi];
+       else if (phba->sli_rev >= LPFC_SLI_REV4)
+               mb->un.varUnregVpi.sli4_vpi = phba->vpi_ids[vpi];
 
        mb->mbxCommand = MBX_UNREG_VPI;
        mb->mbxOwner = OWN_HOST;
@@ -1735,12 +1750,12 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
                return length;
        }
 
-       /* Setup for the none-embedded mbox command */
+       /* Setup for the non-embedded mbox command */
        pcount = (SLI4_PAGE_ALIGN(length))/SLI4_PAGE_SIZE;
        pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ?
                                LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount;
        /* Allocate record for keeping SGE virtual addresses */
-       mbox->sge_array = kmalloc(sizeof(struct lpfc_mbx_nembed_sge_virt),
+       mbox->sge_array = kzalloc(sizeof(struct lpfc_mbx_nembed_sge_virt),
                                  GFP_KERNEL);
        if (!mbox->sge_array) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
@@ -1790,11 +1805,86 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
        /* The sub-header is in DMA memory, which needs endian converstion */
        if (cfg_shdr)
                lpfc_sli_pcimem_bcopy(cfg_shdr, cfg_shdr,
-                             sizeof(union  lpfc_sli4_cfg_shdr));
-
+                                     sizeof(union  lpfc_sli4_cfg_shdr));
        return alloc_len;
 }
 
+/**
+ * lpfc_sli4_mbox_rsrc_extent - Initialize the opcode resource extent.
+ * @phba: pointer to lpfc hba data structure.
+ * @mbox: pointer to an allocated lpfc mbox resource.
+ * @exts_count: the number of extents, if required, to allocate.
+ * @rsrc_type: the resource extent type.
+ * @emb: true if LPFC_SLI4_MBX_EMBED. false if LPFC_SLI4_MBX_NEMBED.
+ *
+ * This routine completes the subcommand header for SLI4 resource extent
+ * mailbox commands.  It is called after lpfc_sli4_config.  The caller must
+ * pass an allocated mailbox and the attributes required to initialize the
+ * mailbox correctly.
+ *
+ * Return: the actual length of the mbox command allocated.
+ **/
+int
+lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
+                          uint16_t exts_count, uint16_t rsrc_type, bool emb)
+{
+       uint8_t opcode = 0;
+       struct lpfc_mbx_nembed_rsrc_extent *n_rsrc_extnt = NULL;
+       void *virtaddr = NULL;
+
+       /* Set up SLI4 ioctl command header fields */
+       if (emb == LPFC_SLI4_MBX_NEMBED) {
+               /* Get the first SGE entry from the non-embedded DMA memory */
+               virtaddr = mbox->sge_array->addr[0];
+               if (virtaddr == NULL)
+                       return 1;
+               n_rsrc_extnt = (struct lpfc_mbx_nembed_rsrc_extent *) virtaddr;
+       }
+
+       /*
+        * The resource type is common to all extent Opcodes and resides in the
+        * same position.
+        */
+       if (emb == LPFC_SLI4_MBX_EMBED)
+               bf_set(lpfc_mbx_alloc_rsrc_extents_type,
+                      &mbox->u.mqe.un.alloc_rsrc_extents.u.req,
+                      rsrc_type);
+       else {
+               /* This is DMA data.  Byteswap is required. */
+               bf_set(lpfc_mbx_alloc_rsrc_extents_type,
+                      n_rsrc_extnt, rsrc_type);
+               lpfc_sli_pcimem_bcopy(&n_rsrc_extnt->word4,
+                                     &n_rsrc_extnt->word4,
+                                     sizeof(uint32_t));
+       }
+
+       /* Complete the initialization for the particular Opcode. */
+       opcode = lpfc_sli4_mbox_opcode_get(phba, mbox);
+       switch (opcode) {
+       case LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT:
+               if (emb == LPFC_SLI4_MBX_EMBED)
+                       bf_set(lpfc_mbx_alloc_rsrc_extents_cnt,
+                              &mbox->u.mqe.un.alloc_rsrc_extents.u.req,
+                              exts_count);
+               else
+                       bf_set(lpfc_mbx_alloc_rsrc_extents_cnt,
+                              n_rsrc_extnt, exts_count);
+               break;
+       case LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT:
+       case LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO:
+       case LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT:
+               /* Initialization is complete.*/
+               break;
+       default:
+               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+                               "2929 Resource Extent Opcode x%x is "
+                               "unsupported\n", opcode);
+               return 1;
+       }
+
+       return 0;
+}
+
 /**
  * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command
  * @phba: pointer to lpfc hba data structure.
@@ -1939,9 +2029,12 @@ lpfc_init_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport)
        bf_set(lpfc_init_vfi_vr, init_vfi, 1);
        bf_set(lpfc_init_vfi_vt, init_vfi, 1);
        bf_set(lpfc_init_vfi_vp, init_vfi, 1);
-       bf_set(lpfc_init_vfi_vfi, init_vfi, vport->vfi + vport->phba->vfi_base);
-       bf_set(lpfc_init_vpi_vpi, init_vfi, vport->vpi + vport->phba->vpi_base);
-       bf_set(lpfc_init_vfi_fcfi, init_vfi, vport->phba->fcf.fcfi);
+       bf_set(lpfc_init_vfi_vfi, init_vfi,
+              vport->phba->sli4_hba.vfi_ids[vport->vfi]);
+       bf_set(lpfc_init_vfi_vpi, init_vfi,
+              vport->phba->vpi_ids[vport->vpi]);
+       bf_set(lpfc_init_vfi_fcfi, init_vfi,
+              vport->phba->fcf.fcfi);
 }
 
 /**
@@ -1964,9 +2057,10 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
        reg_vfi = &mbox->u.mqe.un.reg_vfi;
        bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_REG_VFI);
        bf_set(lpfc_reg_vfi_vp, reg_vfi, 1);
-       bf_set(lpfc_reg_vfi_vfi, reg_vfi, vport->vfi + vport->phba->vfi_base);
+       bf_set(lpfc_reg_vfi_vfi, reg_vfi,
+              vport->phba->sli4_hba.vfi_ids[vport->vfi]);
        bf_set(lpfc_reg_vfi_fcfi, reg_vfi, vport->phba->fcf.fcfi);
-       bf_set(lpfc_reg_vfi_vpi, reg_vfi, vport->vpi + vport->phba->vpi_base);
+       bf_set(lpfc_reg_vfi_vpi, reg_vfi, vport->phba->vpi_ids[vport->vpi]);
        memcpy(reg_vfi->wwn, &vport->fc_portname, sizeof(struct lpfc_name));
        reg_vfi->wwn[0] = cpu_to_le32(reg_vfi->wwn[0]);
        reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]);
@@ -1997,9 +2091,9 @@ lpfc_init_vpi(struct lpfc_hba *phba, struct lpfcMboxq *mbox, uint16_t vpi)
        memset(mbox, 0, sizeof(*mbox));
        bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VPI);
        bf_set(lpfc_init_vpi_vpi, &mbox->u.mqe.un.init_vpi,
-              vpi + phba->vpi_base);
+              phba->vpi_ids[vpi]);
        bf_set(lpfc_init_vpi_vfi, &mbox->u.mqe.un.init_vpi,
-              phba->pport->vfi + phba->vfi_base);
+              phba->sli4_hba.vfi_ids[phba->pport->vfi]);
 }
 
 /**
@@ -2019,7 +2113,7 @@ lpfc_unreg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport)
        memset(mbox, 0, sizeof(*mbox));
        bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_UNREG_VFI);
        bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi,
-              vport->vfi + vport->phba->vfi_base);
+              vport->phba->sli4_hba.vfi_ids[vport->vfi]);
 }
 
 /**
@@ -2131,12 +2225,14 @@ lpfc_unreg_fcfi(struct lpfcMboxq *mbox, uint16_t fcfi)
 void
 lpfc_resume_rpi(struct lpfcMboxq *mbox, struct lpfc_nodelist *ndlp)
 {
+       struct lpfc_hba *phba = ndlp->phba;
        struct lpfc_mbx_resume_rpi *resume_rpi;
 
        memset(mbox, 0, sizeof(*mbox));
        resume_rpi = &mbox->u.mqe.un.resume_rpi;
        bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_RESUME_RPI);
-       bf_set(lpfc_resume_rpi_index, resume_rpi, ndlp->nlp_rpi);
+       bf_set(lpfc_resume_rpi_index, resume_rpi,
+              phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
        bf_set(lpfc_resume_rpi_ii, resume_rpi, RESUME_INDEX_RPI);
        resume_rpi->event_tag = ndlp->phba->fc_eventTag;
 }