[SCSI] lpfc 8.3.3 : Fix various SLI-3 vs SLI-4 differences
authorJames Smart <James.Smart@Emulex.Com>
Wed, 10 Jun 2009 21:22:44 +0000 (17:22 -0400)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Mon, 15 Jun 2009 15:09:32 +0000 (10:09 -0500)
Contains the following changes
- Set the CT field of FDISC to 3
- Fixed over allocation of SCSI buffers on SLI4
- Removed unused jump table entries
- Increase LPFC_WQE_DEF_COUNT to 256
- Updated FDISC context to VPI
- Fixed immediate SCSI command for LUN reset translation to WQE
- Extended mailbox handling to allow MBX_POLL commands in between async
  MBQ commands
- Fixed SID used for FDISC
- Fix crash when accessing ctlregs from sysfs for SLI4 HBAs
- Fix SLI4 firmware version not being saved or displayed correctly
- Expand CQID field in WQE structure to 16 bits
- Fix post header template mailbox command timing out
- Removed FCoE PCI device ID 0x0705

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h

index 540569849099fc88cd774b2ce2549f1f586d0196..1877d9811831c1f3a39b0b14aff1ca5868ebb692 100644 (file)
@@ -457,10 +457,6 @@ struct lpfc_hba {
        void (*lpfc_scsi_prep_cmnd)
                (struct lpfc_vport *, struct lpfc_scsi_buf *,
                 struct lpfc_nodelist *);
-       int (*lpfc_scsi_prep_task_mgmt_cmd)
-               (struct lpfc_vport *, struct lpfc_scsi_buf *,
-                unsigned int, uint8_t);
-
        /* IOCB interface function jump table entries */
        int (*__lpfc_sli_issue_iocb)
                (struct lpfc_hba *, uint32_t,
index d73e677201f8df229784fce5fc48e039dba7ae56..fc07be5fbce9e1464cd3835e511eba57942c5401 100644 (file)
@@ -3113,6 +3113,9 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
        struct lpfc_hba   *phba = vport->phba;
 
+       if (phba->sli_rev >= LPFC_SLI_REV4)
+               return -EPERM;
+
        if ((off + count) > FF_REG_AREA_SIZE)
                return -ERANGE;
 
@@ -3163,6 +3166,9 @@ sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
        struct lpfc_hba   *phba = vport->phba;
 
+       if (phba->sli_rev >= LPFC_SLI_REV4)
+               return -EPERM;
+
        if (off > FF_REG_AREA_SIZE)
                return -ERANGE;
 
index 1dbccfd3d022a6339bad81a04f291ec41abe89fb..0e532f072eb3621f45964f48ba7a0beb4576d2b3 100644 (file)
@@ -1732,7 +1732,9 @@ lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
        uint32_t *ptr, str[4];
        uint8_t *fwname;
 
-       if (vp->rev.rBit) {
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               sprintf(fwrevision, "%s", vp->rev.opFwName);
+       else if (vp->rev.rBit) {
                if (psli->sli_flag & LPFC_SLI_ACTIVE)
                        rev = vp->rev.sli2FwRev;
                else
index 6bdeb14878a2b094eb7f175bea7982cdd337b957..2aabaf9c4053adfb98c9e20f3126dbc6a5c40006 100644 (file)
@@ -6108,9 +6108,17 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        icmd->un.elsreq64.myID = 0;
        icmd->un.elsreq64.fl = 1;
 
-       /* For FDISC, Let FDISC rsp set the NPortID for this VPI */
-       icmd->ulpCt_h = 1;
-       icmd->ulpCt_l = 0;
+       if  (phba->sli_rev == LPFC_SLI_REV4) {
+               /* FDISC needs to be 1 for WQE VPI */
+               elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1;
+               elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ;
+               /* Set the ulpContext to the vpi */
+               elsiocb->iocb.ulpContext = vport->vpi + phba->vpi_base;
+       } else {
+               /* For FDISC, Let FDISC rsp set the NPortID for this VPI */
+               icmd->ulpCt_h = 1;
+               icmd->ulpCt_l = 0;
+       }
 
        pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
        *((uint32_t *) (pcmd)) = ELS_CMD_FDISC;
index 02aa016b93e926c2f6808f2e83d353e10359df55..8a3a026667e42749342e3e106c83fb0a9dfd6765 100644 (file)
@@ -1183,7 +1183,6 @@ typedef struct {
 #define PCI_DEVICE_ID_ZEPHYR_DCSP   0xfe12
 #define PCI_VENDOR_ID_SERVERENGINE  0x19a2
 #define PCI_DEVICE_ID_TIGERSHARK    0x0704
-#define PCI_DEVICE_ID_TIGERSHARK_S  0x0705
 
 #define JEDEC_ID_ADDRESS            0x0080001c
 #define FIREFLY_JEDEC_ID            0x1ACC
index 39c34b3ad29d768654a8a274728387fdd89f8cb2..749811a1627b3937d7b5c05b99aedbb1010f6104 100644 (file)
@@ -422,9 +422,9 @@ struct lpfc_wqe_generic{
 #define lpfc_wqe_gen_pri_WORD          word10
        uint32_t word11;
 #define lpfc_wqe_gen_cq_id_SHIFT       16
-#define lpfc_wqe_gen_cq_id_MASK                0x000003FF
+#define lpfc_wqe_gen_cq_id_MASK                0x0000FFFF
 #define lpfc_wqe_gen_cq_id_WORD                word11
-#define LPFC_WQE_CQ_ID_DEFAULT 0x3ff
+#define LPFC_WQE_CQ_ID_DEFAULT 0xffff
 #define lpfc_wqe_gen_wqec_SHIFT                7
 #define lpfc_wqe_gen_wqec_MASK         0x00000001
 #define lpfc_wqe_gen_wqec_WORD         word11
index 2f5907f92eeaee7cac3079615ac035d67c27e1a5..4363331aba772b5b5592a98a292bea57e0fa5965 100644 (file)
@@ -428,7 +428,8 @@ lpfc_config_port_post(struct lpfc_hba *phba)
        /* Reset the DFT_HBA_Q_DEPTH to the max xri  */
        if (phba->cfg_hba_queue_depth > (mb->un.varRdConfig.max_xri+1))
                phba->cfg_hba_queue_depth =
-                       mb->un.varRdConfig.max_xri + 1;
+                       (mb->un.varRdConfig.max_xri + 1) -
+                                       lpfc_sli4_get_els_iocb_cnt(phba);
 
        phba->lmt = mb->un.varRdConfig.lmt;
 
@@ -1646,10 +1647,6 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
                oneConnect = 1;
                m = (typeof(m)) {"OCe10100-F", max_speed, "PCIe"};
                break;
-       case PCI_DEVICE_ID_TIGERSHARK_S:
-               oneConnect = 1;
-               m = (typeof(m)) {"OCe10100-F-S", max_speed, "PCIe"};
-               break;
        default:
                m = (typeof(m)){ NULL };
                break;
@@ -7184,16 +7181,19 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba)
 {
        int max_xri = phba->sli4_hba.max_cfg_param.max_xri;
 
-       if (max_xri <= 100)
-               return 4;
-       else if (max_xri <= 256)
-               return 8;
-       else if (max_xri <= 512)
-               return 16;
-       else if (max_xri <= 1024)
-               return 32;
-       else
-               return 48;
+       if (phba->sli_rev == LPFC_SLI_REV4) {
+               if (max_xri <= 100)
+                       return 4;
+               else if (max_xri <= 256)
+                       return 8;
+               else if (max_xri <= 512)
+                       return 16;
+               else if (max_xri <= 1024)
+                       return 32;
+               else
+                       return 48;
+       } else
+               return 0;
 }
 
 /**
@@ -7642,7 +7642,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 
        switch (dev_id) {
        case PCI_DEVICE_ID_TIGERSHARK:
-       case PCI_DEVICE_ID_TIGERSHARK_S:
                rc = lpfc_pci_probe_one_s4(pdev, pid);
                break;
        default:
@@ -7941,8 +7940,6 @@ static struct pci_device_id lpfc_id_table[] = {
                PCI_ANY_ID, PCI_ANY_ID, },
        {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK,
                PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK_S,
-               PCI_ANY_ID, PCI_ANY_ID, },
        { 0 }
 };
 
index e9fa6762044ae9ef398b27b9e44c51a364338528..32f8dac6abfeb95abce0ec5239ab02acd25730e4 100644 (file)
@@ -115,6 +115,27 @@ lpfc_debug_save_dif(struct scsi_cmnd *cmnd)
        }
 }
 
+/**
+ * lpfc_sli4_set_rsp_sgl_last - Set the last bit in the response sge.
+ * @phba: Pointer to HBA object.
+ * @lpfc_cmd: lpfc scsi command object pointer.
+ *
+ * This function is called from the lpfc_prep_task_mgmt_cmd function to
+ * set the last bit in the response sge entry.
+ **/
+static void
+lpfc_sli4_set_rsp_sgl_last(struct lpfc_hba *phba,
+                               struct lpfc_scsi_buf *lpfc_cmd)
+{
+       struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl;
+       if (sgl) {
+               sgl += 1;
+               sgl->word2 = le32_to_cpu(sgl->word2);
+               bf_set(lpfc_sli4_sge_last, sgl, 1);
+               sgl->word2 = cpu_to_le32(sgl->word2);
+       }
+}
+
 /**
  * lpfc_update_stats - Update statistical data for the command completion
  * @phba: Pointer to HBA object.
@@ -1978,7 +1999,7 @@ lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport,
 }
 
 /**
- * lpfc_scsi_unprep_dma_buf_s3 - Un-map DMA mapping of SG-list for SLI3 dev
+ * lpfc_scsi_unprep_dma_buf - Un-map DMA mapping of SG-list for dev
  * @phba: The HBA for which this call is being executed.
  * @psb: The scsi buffer which is going to be un-mapped.
  *
@@ -1986,7 +2007,7 @@ lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport,
  * field of @lpfc_cmd for device with SLI-3 interface spec.
  **/
 static void
-lpfc_scsi_unprep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
+lpfc_scsi_unprep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
 {
        /*
         * There are only two special cases to consider.  (1) the scsi command
@@ -2002,36 +2023,6 @@ lpfc_scsi_unprep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
                                psb->pCmd->sc_data_direction);
 }
 
-/**
- * lpfc_scsi_unprep_dma_buf_s4 - Un-map DMA mapping of SG-list for SLI4 dev
- * @phba: The Hba for which this call is being executed.
- * @psb: The scsi buffer which is going to be un-mapped.
- *
- * This routine does DMA un-mapping of scatter gather list of scsi command
- * field of @lpfc_cmd for device with SLI-4 interface spec. If we have to
- * remove the sgl for this scsi buffer then we will do it here. For now
- * we should be able to just call the sli3 unprep routine.
- **/
-static void
-lpfc_scsi_unprep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
-{
-       lpfc_scsi_unprep_dma_buf_s3(phba, psb);
-}
-
-/**
- * lpfc_scsi_unprep_dma_buf - Wrapper function for unmap DMA mapping of SG-list
- * @phba: The Hba for which this call is being executed.
- * @psb: The scsi buffer which is going to be un-mapped.
- *
- * This routine does DMA un-mapping of scatter gather list of scsi command
- * field of @lpfc_cmd for device with SLI-4 interface spec.
- **/
-static void
-lpfc_scsi_unprep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
-{
-       phba->lpfc_scsi_unprep_dma_buf(phba, psb);
-}
-
 /**
  * lpfc_handler_fcp_err - FCP response handler
  * @vport: The virtual port for which this call is being executed.
@@ -2461,7 +2452,7 @@ lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd)
 }
 
 /**
- * lpfc_scsi_prep_cmnd_s3 - Convert scsi cmnd to FCP infor unit for SLI3 dev
+ * lpfc_scsi_prep_cmnd - Wrapper func for convert scsi cmnd to FCP info unit
  * @vport: The virtual port for which this call is being executed.
  * @lpfc_cmd: The scsi command which needs to send.
  * @pnode: Pointer to lpfc_nodelist.
@@ -2470,7 +2461,7 @@ lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd)
  * to transfer for device with SLI3 interface spec.
  **/
 static void
-lpfc_scsi_prep_cmnd_s3(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
+lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
                    struct lpfc_nodelist *pnode)
 {
        struct lpfc_hba *phba = vport->phba;
@@ -2558,46 +2549,7 @@ lpfc_scsi_prep_cmnd_s3(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
 }
 
 /**
- * lpfc_scsi_prep_cmnd_s4 - Convert scsi cmnd to FCP infor unit for SLI4 dev
- * @vport: The virtual port for which this call is being executed.
- * @lpfc_cmd: The scsi command which needs to send.
- * @pnode: Pointer to lpfc_nodelist.
- *
- * This routine initializes fcp_cmnd and iocb data structure from scsi command
- * to transfer for device with SLI4 interface spec.
- **/
-static void
-lpfc_scsi_prep_cmnd_s4(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
-                      struct lpfc_nodelist *pnode)
-{
-       /*
-        * The prep cmnd routines do not touch the sgl or its
-        * entries. We may not have to do anything different.
-        * I will leave this function in place until we can
-        * run some IO through the driver and determine if changes
-        * are needed.
-        */
-       return lpfc_scsi_prep_cmnd_s3(vport, lpfc_cmd, pnode);
-}
-
-/**
- * lpfc_scsi_prep_cmnd - Wrapper func for convert scsi cmnd to FCP info unit
- * @vport: The virtual port for which this call is being executed.
- * @lpfc_cmd: The scsi command which needs to send.
- * @pnode: Pointer to lpfc_nodelist.
- *
- * This routine wraps the actual convert SCSI cmnd function pointer from
- * the lpfc_hba struct.
- **/
-static inline void
-lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
-                   struct lpfc_nodelist *pnode)
-{
-       vport->phba->lpfc_scsi_prep_cmnd(vport, lpfc_cmd, pnode);
-}
-
-/**
- * lpfc_scsi_prep_task_mgmt_cmnd_s3 - Convert SLI3 scsi TM cmd to FCP info unit
+ * lpfc_scsi_prep_task_mgmt_cmnd - Convert SLI3 scsi TM cmd to FCP info unit
  * @vport: The virtual port for which this call is being executed.
  * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
  * @lun: Logical unit number.
@@ -2611,7 +2563,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
  *   1 - Success
  **/
 static int
-lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport *vport,
+lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
                             struct lpfc_scsi_buf *lpfc_cmd,
                             unsigned int lun,
                             uint8_t task_mgmt_cmd)
@@ -2653,68 +2605,13 @@ lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport *vport,
                 * The driver will provide the timeout mechanism.
                 */
                piocb->ulpTimeout = 0;
-       } else {
+       } else
                piocb->ulpTimeout = lpfc_cmd->timeout;
-       }
-
-       return 1;
-}
-
-/**
- * lpfc_scsi_prep_task_mgmt_cmnd_s4 - Convert SLI4 scsi TM cmd to FCP info unit
- * @vport: The virtual port for which this call is being executed.
- * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
- * @lun: Logical unit number.
- * @task_mgmt_cmd: SCSI task management command.
- *
- * This routine creates FCP information unit corresponding to @task_mgmt_cmd
- * for device with SLI-4 interface spec.
- *
- * Return codes:
- *     0 - Error
- *     1 - Success
- **/
-static int
-lpfc_scsi_prep_task_mgmt_cmd_s4(struct lpfc_vport *vport,
-                               struct lpfc_scsi_buf *lpfc_cmd,
-                               unsigned int lun,
-                               uint8_t task_mgmt_cmd)
-{
-       /*
-        * The prep cmnd routines do not touch the sgl or its
-        * entries. We may not have to do anything different.
-        * I will leave this function in place until we can
-        * run some IO through the driver and determine if changes
-        * are needed.
-        */
-       return lpfc_scsi_prep_task_mgmt_cmd_s3(vport, lpfc_cmd, lun,
-                                               task_mgmt_cmd);
-}
 
-/**
- * lpfc_scsi_prep_task_mgmt_cmnd - Wrapper func convert scsi TM cmd to FCP info
- * @vport: The virtual port for which this call is being executed.
- * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
- * @lun: Logical unit number.
- * @task_mgmt_cmd: SCSI task management command.
- *
- * This routine wraps the actual convert SCSI TM to FCP information unit
- * function pointer from the lpfc_hba struct.
- *
- * Return codes:
- *     0 - Error
- *     1 - Success
- **/
-static inline int
-lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
-                            struct lpfc_scsi_buf *lpfc_cmd,
-                            unsigned int lun,
-                            uint8_t task_mgmt_cmd)
-{
-       struct lpfc_hba *phba = vport->phba;
+       if (vport->phba->sli_rev == LPFC_SLI_REV4)
+               lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd);
 
-       return phba->lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun,
-                                                 task_mgmt_cmd);
+       return 1;
 }
 
 /**
@@ -2730,23 +2627,19 @@ int
 lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
 {
 
+       phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf;
+       phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd;
+       phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf;
+
        switch (dev_grp) {
        case LPFC_PCI_DEV_LP:
                phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s3;
                phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s3;
-               phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd_s3;
-               phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf_s3;
-               phba->lpfc_scsi_prep_task_mgmt_cmd =
-                                       lpfc_scsi_prep_task_mgmt_cmd_s3;
                phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3;
                break;
        case LPFC_PCI_DEV_OC:
                phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s4;
                phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4;
-               phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd_s4;
-               phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf_s4;
-               phba->lpfc_scsi_prep_task_mgmt_cmd =
-                                       lpfc_scsi_prep_task_mgmt_cmd_s4;
                phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4;
                break;
        default:
index ff04daf18f48d1ba4df538638b746c2d87a1236d..b8cf0a1b13822d587a7330eafb234339eff3b7aa 100644 (file)
@@ -4211,27 +4211,6 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
                return -EIO;
        }
 
-       lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
-                       "(%d):0380 Mailbox cmd x%x Status x%x "
-                       "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x "
-                       "x%x x%x x%x x%x x%x x%x x%x x%x x%x "
-                       "CQ: x%x x%x x%x x%x\n",
-                       mboxq->vport ? mboxq->vport->vpi : 0,
-                       bf_get(lpfc_mqe_command, mqe),
-                       bf_get(lpfc_mqe_status, mqe),
-                       mqe->un.mb_words[0], mqe->un.mb_words[1],
-                       mqe->un.mb_words[2], mqe->un.mb_words[3],
-                       mqe->un.mb_words[4], mqe->un.mb_words[5],
-                       mqe->un.mb_words[6], mqe->un.mb_words[7],
-                       mqe->un.mb_words[8], mqe->un.mb_words[9],
-                       mqe->un.mb_words[10], mqe->un.mb_words[11],
-                       mqe->un.mb_words[12], mqe->un.mb_words[13],
-                       mqe->un.mb_words[14], mqe->un.mb_words[15],
-                       mqe->un.mb_words[16], mqe->un.mb_words[50],
-                       mboxq->mcqe.word0,
-                       mboxq->mcqe.mcqe_tag0,  mboxq->mcqe.mcqe_tag1,
-                       mboxq->mcqe.trailer);
-
        /*
         * The available vpd length cannot be bigger than the
         * DMA buffer passed to the port.  Catch the less than
@@ -4337,21 +4316,18 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                goto out_free_vpd;
 
        mqe = &mboxq->u.mqe;
-       if ((bf_get(lpfc_mbx_rd_rev_sli_lvl,
-                   &mqe->un.read_rev) != LPFC_SLI_REV4) ||
-           (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev) == 0)) {
+       phba->sli_rev = bf_get(lpfc_mbx_rd_rev_sli_lvl, &mqe->un.read_rev);
+       if (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev))
+               phba->hba_flag |= HBA_FCOE_SUPPORT;
+       if (phba->sli_rev != LPFC_SLI_REV4 ||
+           !(phba->hba_flag & HBA_FCOE_SUPPORT)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
                        "0376 READ_REV Error. SLI Level %d "
                        "FCoE enabled %d\n",
-                       bf_get(lpfc_mbx_rd_rev_sli_lvl, &mqe->un.read_rev),
-                       bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev));
+                       phba->sli_rev, phba->hba_flag & HBA_FCOE_SUPPORT);
                rc = -EIO;
                goto out_free_vpd;
        }
-       /* Single threaded at this point, no need for lock */
-       spin_lock_irq(&phba->hbalock);
-       phba->hba_flag |= HBA_FCOE_SUPPORT;
-       spin_unlock_irq(&phba->hbalock);
        /*
         * Evaluate the read rev and vpd data. Populate the driver
         * state with the results. If this routine fails, the failure
@@ -4365,8 +4341,32 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                rc = 0;
        }
 
-       /* By now, we should determine the SLI revision, hard code for now */
-       phba->sli_rev = LPFC_SLI_REV4;
+       /* Save information as VPD data */
+       phba->vpd.rev.biuRev = mqe->un.read_rev.first_hw_rev;
+       phba->vpd.rev.smRev = mqe->un.read_rev.second_hw_rev;
+       phba->vpd.rev.endecRev = mqe->un.read_rev.third_hw_rev;
+       phba->vpd.rev.fcphHigh = bf_get(lpfc_mbx_rd_rev_fcph_high,
+                                        &mqe->un.read_rev);
+       phba->vpd.rev.fcphLow = bf_get(lpfc_mbx_rd_rev_fcph_low,
+                                      &mqe->un.read_rev);
+       phba->vpd.rev.feaLevelHigh = bf_get(lpfc_mbx_rd_rev_ftr_lvl_high,
+                                           &mqe->un.read_rev);
+       phba->vpd.rev.feaLevelLow = bf_get(lpfc_mbx_rd_rev_ftr_lvl_low,
+                                          &mqe->un.read_rev);
+       phba->vpd.rev.sli1FwRev = mqe->un.read_rev.fw_id_rev;
+       memcpy(phba->vpd.rev.sli1FwName, mqe->un.read_rev.fw_name, 16);
+       phba->vpd.rev.sli2FwRev = mqe->un.read_rev.ulp_fw_id_rev;
+       memcpy(phba->vpd.rev.sli2FwName, mqe->un.read_rev.ulp_fw_name, 16);
+       phba->vpd.rev.opFwRev = mqe->un.read_rev.fw_id_rev;
+       memcpy(phba->vpd.rev.opFwName, mqe->un.read_rev.fw_name, 16);
+       lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+                       "(%d):0380 READ_REV Status x%x "
+                       "fw_rev:%s fcphHi:%x fcphLo:%x flHi:%x flLo:%x\n",
+                       mboxq->vport ? mboxq->vport->vpi : 0,
+                       bf_get(lpfc_mqe_status, mqe),
+                       phba->vpd.rev.opFwName,
+                       phba->vpd.rev.fcphHigh, phba->vpd.rev.fcphLow,
+                       phba->vpd.rev.feaLevelHigh, phba->vpd.rev.feaLevelLow);
 
        /*
         * Discover the port's supported feature set and match it against the
@@ -5029,6 +5029,92 @@ out_not_finished:
        return MBX_NOT_FINISHED;
 }
 
+/**
+ * lpfc_sli4_async_mbox_block - Block posting SLI4 asynchronous mailbox command
+ * @phba: Pointer to HBA context object.
+ *
+ * The function blocks the posting of SLI4 asynchronous mailbox commands from
+ * the driver internal pending mailbox queue. It will then try to wait out the
+ * possible outstanding mailbox command before return.
+ *
+ * Returns:
+ *     0 - the outstanding mailbox command completed; otherwise, the wait for
+ *     the outstanding mailbox command timed out.
+ **/
+static int
+lpfc_sli4_async_mbox_block(struct lpfc_hba *phba)
+{
+       struct lpfc_sli *psli = &phba->sli;
+       uint8_t actcmd = MBX_HEARTBEAT;
+       int rc = 0;
+       unsigned long timeout;
+
+       /* Mark the asynchronous mailbox command posting as blocked */
+       spin_lock_irq(&phba->hbalock);
+       psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK;
+       if (phba->sli.mbox_active)
+               actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
+       spin_unlock_irq(&phba->hbalock);
+       /* Determine how long we might wait for the active mailbox
+        * command to be gracefully completed by firmware.
+        */
+       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) +
+                                  jiffies;
+       /* Wait for the outstnading mailbox command to complete */
+       while (phba->sli.mbox_active) {
+               /* Check active mailbox complete status every 2ms */
+               msleep(2);
+               if (time_after(jiffies, timeout)) {
+                       /* Timeout, marked the outstanding cmd not complete */
+                       rc = 1;
+                       break;
+               }
+       }
+
+       /* Can not cleanly block async mailbox command, fails it */
+       if (rc) {
+               spin_lock_irq(&phba->hbalock);
+               psli->sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
+               spin_unlock_irq(&phba->hbalock);
+       }
+       return rc;
+}
+
+/**
+ * lpfc_sli4_async_mbox_unblock - Block posting SLI4 async mailbox command
+ * @phba: Pointer to HBA context object.
+ *
+ * The function unblocks and resume posting of SLI4 asynchronous mailbox
+ * commands from the driver internal pending mailbox queue. It makes sure
+ * that there is no outstanding mailbox command before resuming posting
+ * asynchronous mailbox commands. If, for any reason, there is outstanding
+ * mailbox command, it will try to wait it out before resuming asynchronous
+ * mailbox command posting.
+ **/
+static void
+lpfc_sli4_async_mbox_unblock(struct lpfc_hba *phba)
+{
+       struct lpfc_sli *psli = &phba->sli;
+
+       spin_lock_irq(&phba->hbalock);
+       if (!(psli->sli_flag & LPFC_SLI_ASYNC_MBX_BLK)) {
+               /* Asynchronous mailbox posting is not blocked, do nothing */
+               spin_unlock_irq(&phba->hbalock);
+               return;
+       }
+
+       /* Outstanding synchronous mailbox command is guaranteed to be done,
+        * successful or timeout, after timing-out the outstanding mailbox
+        * command shall always be removed, so just unblock posting async
+        * mailbox command and resume
+        */
+       psli->sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
+       spin_unlock_irq(&phba->hbalock);
+
+       /* wake up worker thread to post asynchronlous mailbox command */
+       lpfc_worker_wake_up(phba);
+}
+
 /**
  * lpfc_sli4_post_sync_mbox - Post an SLI4 mailbox to the bootstrap mailbox
  * @phba: Pointer to HBA context object.
@@ -5204,14 +5290,35 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
                                        psli->sli_flag, flag);
                return rc;
        } else if (flag == MBX_POLL) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-                               "(%d):2542 Mailbox command x%x (x%x) "
-                               "cannot issue Data: x%x x%x\n",
+               lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+                               "(%d):2542 Try to issue mailbox command "
+                               "x%x (x%x) synchronously ahead of async"
+                               "mailbox command queue: x%x x%x\n",
                                mboxq->vport ? mboxq->vport->vpi : 0,
                                mboxq->u.mb.mbxCommand,
                                lpfc_sli4_mbox_opcode_get(phba, mboxq),
                                psli->sli_flag, flag);
-               return -EIO;
+               /* Try to block the asynchronous mailbox posting */
+               rc = lpfc_sli4_async_mbox_block(phba);
+               if (!rc) {
+                       /* Successfully blocked, now issue sync mbox cmd */
+                       rc = lpfc_sli4_post_sync_mbox(phba, mboxq);
+                       if (rc != MBX_SUCCESS)
+                               lpfc_printf_log(phba, KERN_ERR,
+                                               LOG_MBOX | LOG_SLI,
+                                               "(%d):2597 Mailbox command "
+                                               "x%x (x%x) cannot issue "
+                                               "Data: x%x x%x\n",
+                                               mboxq->vport ?
+                                               mboxq->vport->vpi : 0,
+                                               mboxq->u.mb.mbxCommand,
+                                               lpfc_sli4_mbox_opcode_get(phba,
+                                                               mboxq),
+                                               psli->sli_flag, flag);
+                       /* Unblock the async mailbox posting afterward */
+                       lpfc_sli4_async_mbox_unblock(phba);
+               }
+               return rc;
        }
 
        /* Now, interrupt mode asynchrous mailbox command */
@@ -5814,11 +5921,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(lpfc_wqe_gen_context, &wqe->generic,
                                iocbq->iocb.ulpContext);
 
-               if (iocbq->vport->fc_myDID != 0) {
-                       bf_set(els_req64_sid, &wqe->els_req,
-                                iocbq->vport->fc_myDID);
-                       bf_set(els_req64_sp, &wqe->els_req, 1);
-               }
                bf_set(lpfc_wqe_gen_ct, &wqe->generic, ct);
                bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0);
                /* CCP CCPE PV PRI in word10 were set in the memcpy */
@@ -5877,14 +5979,19 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                 * is set and we are sending our 2nd or greater command on
                 * this exchange.
                 */
+               /* Always open the exchange */
+               bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0);
 
-       /* ALLOW read & write to fall through to ICMD64 */
+               wqe->words[10] &= 0xffff0000; /* zero out ebde count */
+               bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU);
+               break;
        case CMD_FCP_ICMND64_CR:
                /* Always open the exchange */
                bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0);
 
+               wqe->words[4] = 0;
                wqe->words[10] &= 0xffff0000; /* zero out ebde count */
-               bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU);
+               bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0);
        break;
        case CMD_GEN_REQUEST64_CR:
                /* word3 command length is described as byte offset to the
@@ -11020,10 +11127,7 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
               rpi_page->start_rpi);
        hdr_tmpl->rpi_paddr_lo = putPaddrLow(rpi_page->dmabuf->phys);
        hdr_tmpl->rpi_paddr_hi = putPaddrHigh(rpi_page->dmabuf->phys);
-       if (!phba->sli4_hba.intr_enable)
-               rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-       else
-               rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
        shdr = (union lpfc_sli4_cfg_shdr *) &hdr_tmpl->header.cfg_shdr;
        shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
        shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
index 5196b46608d779901c35e502bbbbf7299614a757..3b276b47d18f7220e127d140f1191e21935af2a4 100644 (file)
@@ -229,7 +229,7 @@ struct lpfc_bmbx {
 
 #define LPFC_EQE_DEF_COUNT     1024
 #define LPFC_CQE_DEF_COUNT      256
-#define LPFC_WQE_DEF_COUNT      64
+#define LPFC_WQE_DEF_COUNT      256
 #define LPFC_MQE_DEF_COUNT      16
 #define LPFC_RQE_DEF_COUNT     512