scsi: lpfc: Support duration field in Link Cable Beacon V1 command
authorJames Smart <jsmart2021@gmail.com>
Tue, 26 Jun 2018 15:24:27 +0000 (08:24 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 11 Jul 2018 02:15:09 +0000 (22:15 -0400)
Current implementation missed setting the duration field. Correct the code
to set the field.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
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_sli4.h

index 6d84a10fef0791b8d70750192ffd63c8e9442de4..4683154842f5e30eb97997103887bc58911db0e9 100644 (file)
@@ -5640,8 +5640,9 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                " mbx status x%x\n",
                                shdr_status, shdr_add_status, mb->mbxStatus);
 
-       if (mb->mbxStatus && !(shdr_status &&
-               shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE)) {
+       if ((mb->mbxStatus != MBX_SUCCESS) || shdr_status ||
+           (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE) ||
+           (shdr_add_status == ADD_STATUS_INVALID_REQUEST)) {
                mempool_free(pmb, phba->mbox_mem_pool);
                goto error;
        }
@@ -5670,6 +5671,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        lcb_res->lcb_sub_command = lcb_context->sub_command;
        lcb_res->lcb_type = lcb_context->type;
        lcb_res->lcb_frequency = lcb_context->frequency;
+       lcb_res->lcb_duration = lcb_context->duration;
        elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
        phba->fc_stat.elsXmitACC++;
        rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
@@ -5712,6 +5714,7 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
                     uint32_t beacon_state)
 {
        struct lpfc_hba *phba = vport->phba;
+       union lpfc_sli4_cfg_shdr *cfg_shdr;
        LPFC_MBOXQ_t *mbox = NULL;
        uint32_t len;
        int rc;
@@ -5720,6 +5723,7 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
        if (!mbox)
                return 1;
 
+       cfg_shdr = &mbox->u.mqe.un.sli4_config.header.cfg_shdr;
        len = sizeof(struct lpfc_mbx_set_beacon_config) -
                sizeof(struct lpfc_sli4_cfg_mhdr);
        lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
@@ -5732,8 +5736,40 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
               phba->sli4_hba.physical_port);
        bf_set(lpfc_mbx_set_beacon_state, &mbox->u.mqe.un.beacon_config,
               beacon_state);
-       bf_set(lpfc_mbx_set_beacon_port_type, &mbox->u.mqe.un.beacon_config, 1);
-       bf_set(lpfc_mbx_set_beacon_duration, &mbox->u.mqe.un.beacon_config, 0);
+       mbox->u.mqe.un.beacon_config.word5 = 0;         /* Reserved */
+
+       /*
+        *      Check bv1s bit before issuing the mailbox
+        *      if bv1s == 1, LCB V1 supported
+        *      else, LCB V0 supported
+        */
+
+       if (phba->sli4_hba.pc_sli4_params.bv1s) {
+               /* COMMON_SET_BEACON_CONFIG_V1 */
+               cfg_shdr->request.word9 = BEACON_VERSION_V1;
+               lcb_context->capability |= LCB_CAPABILITY_DURATION;
+               bf_set(lpfc_mbx_set_beacon_port_type,
+                      &mbox->u.mqe.un.beacon_config, 0);
+               bf_set(lpfc_mbx_set_beacon_duration_v1,
+                      &mbox->u.mqe.un.beacon_config,
+                      be16_to_cpu(lcb_context->duration));
+       } else {
+               /* COMMON_SET_BEACON_CONFIG_V0 */
+               if (be16_to_cpu(lcb_context->duration) != 0) {
+                       mempool_free(mbox, phba->mbox_mem_pool);
+                       return 1;
+               }
+               cfg_shdr->request.word9 = BEACON_VERSION_V0;
+               lcb_context->capability &=  ~(LCB_CAPABILITY_DURATION);
+               bf_set(lpfc_mbx_set_beacon_state,
+                      &mbox->u.mqe.un.beacon_config, beacon_state);
+               bf_set(lpfc_mbx_set_beacon_port_type,
+                      &mbox->u.mqe.un.beacon_config, 1);
+               bf_set(lpfc_mbx_set_beacon_duration,
+                      &mbox->u.mqe.un.beacon_config,
+                      be16_to_cpu(lcb_context->duration));
+       }
+
        rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
        if (rc == MBX_NOT_FINISHED) {
                mempool_free(mbox, phba->mbox_mem_pool);
@@ -5784,24 +5820,16 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                        beacon->lcb_frequency,
                        be16_to_cpu(beacon->lcb_duration));
 
-       if (phba->sli_rev < LPFC_SLI_REV4 ||
-           (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
-           LPFC_SLI_INTF_IF_TYPE_2)) {
-               rjt_err = LSRJT_CMD_UNSUPPORTED;
-               goto rjt;
-       }
-
-       if (phba->hba_flag & HBA_FCOE_MODE) {
-               rjt_err = LSRJT_CMD_UNSUPPORTED;
-               goto rjt;
-       }
        if (beacon->lcb_sub_command != LPFC_LCB_ON &&
            beacon->lcb_sub_command != LPFC_LCB_OFF) {
                rjt_err = LSRJT_CMD_UNSUPPORTED;
                goto rjt;
        }
-       if (beacon->lcb_sub_command == LPFC_LCB_ON &&
-           be16_to_cpu(beacon->lcb_duration) != 0) {
+
+       if (phba->sli_rev < LPFC_SLI_REV4  ||
+           phba->hba_flag & HBA_FCOE_MODE ||
+           (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <
+           LPFC_SLI_INTF_IF_TYPE_2)) {
                rjt_err = LSRJT_CMD_UNSUPPORTED;
                goto rjt;
        }
@@ -5814,8 +5842,10 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
 
        state = (beacon->lcb_sub_command == LPFC_LCB_ON) ? 1 : 0;
        lcb_context->sub_command = beacon->lcb_sub_command;
+       lcb_context->capability = 0;
        lcb_context->type = beacon->lcb_type;
        lcb_context->frequency = beacon->lcb_frequency;
+       lcb_context->duration = beacon->lcb_duration;
        lcb_context->ox_id = cmdiocb->iocb.unsli3.rcvsli3.ox_id;
        lcb_context->rx_id = cmdiocb->iocb.ulpContext;
        lcb_context->ndlp = lpfc_nlp_get(ndlp);
index 08a3f15201593a6af9ca77e380d4df2cf553bd1e..f6dcabe27ca1786994e79fb55c30cded2caed9f8 100644 (file)
@@ -1065,14 +1065,17 @@ typedef struct _ELS_PKT {       /* Structure is in Big Endian format */
 struct fc_lcb_request_frame {
        uint32_t      lcb_command;      /* ELS command opcode (0x81)     */
        uint8_t       lcb_sub_command;/* LCB Payload Word 1, bit 24:31 */
-#define LPFC_LCB_ON    0x1
-#define LPFC_LCB_OFF   0x2
-       uint8_t       reserved[3];
-
+#define LPFC_LCB_ON            0x1
+#define LPFC_LCB_OFF           0x2
+       uint8_t       reserved[2];
+       uint8_t       capability;       /* LCB Payload Word 1, bit 0:7 */
        uint8_t       lcb_type; /* LCB Payload Word 2, bit 24:31 */
-#define LPFC_LCB_GREEN 0x1
-#define LPFC_LCB_AMBER 0x2
+#define LPFC_LCB_GREEN         0x1
+#define LPFC_LCB_AMBER         0x2
        uint8_t       lcb_frequency;    /* LCB Payload Word 2, bit 16:23 */
+#define LCB_CAPABILITY_DURATION        1
+#define BEACON_VERSION_V1      1
+#define BEACON_VERSION_V0      0
        uint16_t      lcb_duration;     /* LCB Payload Word 2, bit 15:0  */
 };
 
@@ -1082,7 +1085,8 @@ struct fc_lcb_request_frame {
 struct fc_lcb_res_frame {
        uint32_t      lcb_ls_acc;       /* Acceptance of LCB request (0x02) */
        uint8_t       lcb_sub_command;/* LCB Payload Word 1, bit 24:31 */
-       uint8_t       reserved[3];
+       uint8_t       reserved[2];
+       uint8_t       capability;       /* LCB Payload Word 1, bit 0:7 */
        uint8_t       lcb_type; /* LCB Payload Word 2, bit 24:31 */
        uint8_t       lcb_frequency;    /* LCB Payload Word 2, bit 16:23 */
        uint16_t      lcb_duration;     /* LCB Payload Word 2, bit 15:0  */
index f43f0bacb77a283381cd15afc904a0ed894b3119..083f8c8706e51a609550e35c4a35bccc33b0991b 100644 (file)
@@ -1790,9 +1790,12 @@ struct lpfc_mbx_set_beacon_config {
 #define lpfc_mbx_set_beacon_duration_SHIFT             16
 #define lpfc_mbx_set_beacon_duration_MASK              0x000000FF
 #define lpfc_mbx_set_beacon_duration_WORD              word4
-#define lpfc_mbx_set_beacon_status_duration_SHIFT      24
-#define lpfc_mbx_set_beacon_status_duration_MASK       0x000000FF
-#define lpfc_mbx_set_beacon_status_duration_WORD       word4
+
+/* COMMON_SET_BEACON_CONFIG_V1 */
+#define lpfc_mbx_set_beacon_duration_v1_SHIFT          16
+#define lpfc_mbx_set_beacon_duration_v1_MASK           0x0000FFFF
+#define lpfc_mbx_set_beacon_duration_v1_WORD           word4
+       uint32_t word5;  /* RESERVED  */
 };
 
 struct lpfc_id_range {
@@ -2243,6 +2246,7 @@ struct lpfc_mbx_redisc_fcf_tbl {
  */
 #define ADD_STATUS_OPERATION_ALREADY_ACTIVE            0x67
 #define ADD_STATUS_FW_NOT_SUPPORTED                    0xEB
+#define ADD_STATUS_INVALID_REQUEST                     0x4B
 
 struct lpfc_mbx_sli4_config {
        struct mbox_header header;
@@ -3392,7 +3396,41 @@ struct lpfc_sli4_parameters {
 #define cfg_nosr_SHIFT                         9
 #define cfg_nosr_MASK                          0x00000001
 #define cfg_nosr_WORD                          word19
-#define LPFC_NODELAY_MAX_IO            32
+
+#define cfg_bv1s_SHIFT                          10
+#define cfg_bv1s_MASK                           0x00000001
+#define cfg_bv1s_WORD                           word19
+
+       uint32_t word20;
+#define cfg_max_tow_xri_SHIFT                  0
+#define cfg_max_tow_xri_MASK                   0x0000ffff
+#define cfg_max_tow_xri_WORD                   word20
+
+       uint32_t word21;                        /* RESERVED */
+       uint32_t word22;                        /* RESERVED */
+       uint32_t word23;                        /* RESERVED */
+
+       uint32_t word24;
+#define cfg_frag_field_offset_SHIFT            0
+#define cfg_frag_field_offset_MASK             0x0000ffff
+#define cfg_frag_field_offset_WORD             word24
+
+#define cfg_frag_field_size_SHIFT              16
+#define cfg_frag_field_size_MASK               0x0000ffff
+#define cfg_frag_field_size_WORD               word24
+
+       uint32_t word25;
+#define cfg_sgl_field_offset_SHIFT             0
+#define cfg_sgl_field_offset_MASK              0x0000ffff
+#define cfg_sgl_field_offset_WORD              word25
+
+#define cfg_sgl_field_size_SHIFT               16
+#define cfg_sgl_field_size_MASK                        0x0000ffff
+#define cfg_sgl_field_size_WORD                        word25
+
+       uint32_t word26;        /* Chain SGE initial value LOW  */
+       uint32_t word27;        /* Chain SGE initial value HIGH */
+#define LPFC_NODELAY_MAX_IO                    32
 };
 
 #define LPFC_SET_UE_RECOVERY           0x10
index f2f3b27d0b84302ce8eb7871bff322158bc3ab7e..f3cae733ae2dffea29e37ff562853c2260f9b681 100644 (file)
@@ -10644,6 +10644,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        sli4_params->eqav = bf_get(cfg_eqav, mbx_sli4_parameters);
        sli4_params->cqav = bf_get(cfg_cqav, mbx_sli4_parameters);
        sli4_params->wqsize = bf_get(cfg_wqsize, mbx_sli4_parameters);
+       sli4_params->bv1s = bf_get(cfg_bv1s, mbx_sli4_parameters);
        sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt,
                                            mbx_sli4_parameters);
        sli4_params->wqpcnt = bf_get(cfg_wqpcnt, mbx_sli4_parameters);
index cf64aca82bd059dceccd7779da96c15fa35cb87d..ada68de970b3d3178cc055c9566288618650c354 100644 (file)
@@ -490,6 +490,7 @@ struct lpfc_pc_sli4_params {
        uint8_t eqav;
        uint8_t cqav;
        uint8_t wqsize;
+       uint8_t bv1s;
 #define LPFC_WQ_SZ64_SUPPORT   1
 #define LPFC_WQ_SZ128_SUPPORT  2
        uint8_t wqpcnt;
@@ -774,7 +775,9 @@ struct lpfc_rdp_context {
 struct lpfc_lcb_context {
        uint8_t  sub_command;
        uint8_t  type;
+       uint8_t  capability;
        uint8_t  frequency;
+       uint16_t  duration;
        uint16_t ox_id;
        uint16_t rx_id;
        struct lpfc_nodelist *ndlp;