From 66e9e6bf07cb0a2d4bbccebf6a6f1f27e6768e38 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 26 Jun 2018 08:24:27 -0700 Subject: scsi: lpfc: Support duration field in Link Cable Beacon V1 command Current implementation missed setting the duration field. Correct the code to set the field. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 64 +++++++++++++++++++++++++++++++------------ drivers/scsi/lpfc/lpfc_hw.h | 18 +++++++----- drivers/scsi/lpfc/lpfc_hw4.h | 46 ++++++++++++++++++++++++++++--- drivers/scsi/lpfc/lpfc_init.c | 1 + drivers/scsi/lpfc/lpfc_sli4.h | 3 ++ 5 files changed, 104 insertions(+), 28 deletions(-) (limited to 'drivers/scsi/lpfc') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6d84a10fef07..4683154842f5 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -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); diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 08a3f1520159..f6dcabe27ca1 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -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 */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index f43f0bacb77a..083f8c8706e5 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -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 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f2f3b27d0b84..f3cae733ae2d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -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); diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index cf64aca82bd0..ada68de970b3 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -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; -- cgit v1.2.3