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 <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
James Smart 2018-06-26 08:24:27 -07:00 committed by Martin K. Petersen
parent 414abe0ab6
commit 66e9e6bf07
5 changed files with 104 additions and 28 deletions

View File

@ -5640,8 +5640,9 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
" mbx status x%x\n", " mbx status x%x\n",
shdr_status, shdr_add_status, mb->mbxStatus); shdr_status, shdr_add_status, mb->mbxStatus);
if (mb->mbxStatus && !(shdr_status && if ((mb->mbxStatus != MBX_SUCCESS) || shdr_status ||
shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE)) { (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE) ||
(shdr_add_status == ADD_STATUS_INVALID_REQUEST)) {
mempool_free(pmb, phba->mbox_mem_pool); mempool_free(pmb, phba->mbox_mem_pool);
goto error; 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_sub_command = lcb_context->sub_command;
lcb_res->lcb_type = lcb_context->type; lcb_res->lcb_type = lcb_context->type;
lcb_res->lcb_frequency = lcb_context->frequency; lcb_res->lcb_frequency = lcb_context->frequency;
lcb_res->lcb_duration = lcb_context->duration;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
phba->fc_stat.elsXmitACC++; phba->fc_stat.elsXmitACC++;
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); 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) uint32_t beacon_state)
{ {
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
union lpfc_sli4_cfg_shdr *cfg_shdr;
LPFC_MBOXQ_t *mbox = NULL; LPFC_MBOXQ_t *mbox = NULL;
uint32_t len; uint32_t len;
int rc; int rc;
@ -5720,6 +5723,7 @@ lpfc_sli4_set_beacon(struct lpfc_vport *vport,
if (!mbox) if (!mbox)
return 1; return 1;
cfg_shdr = &mbox->u.mqe.un.sli4_config.header.cfg_shdr;
len = sizeof(struct lpfc_mbx_set_beacon_config) - len = sizeof(struct lpfc_mbx_set_beacon_config) -
sizeof(struct lpfc_sli4_cfg_mhdr); sizeof(struct lpfc_sli4_cfg_mhdr);
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, 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); phba->sli4_hba.physical_port);
bf_set(lpfc_mbx_set_beacon_state, &mbox->u.mqe.un.beacon_config, bf_set(lpfc_mbx_set_beacon_state, &mbox->u.mqe.un.beacon_config,
beacon_state); beacon_state);
bf_set(lpfc_mbx_set_beacon_port_type, &mbox->u.mqe.un.beacon_config, 1); mbox->u.mqe.un.beacon_config.word5 = 0; /* Reserved */
bf_set(lpfc_mbx_set_beacon_duration, &mbox->u.mqe.un.beacon_config, 0);
/*
* 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); rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) { if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool); 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, beacon->lcb_frequency,
be16_to_cpu(beacon->lcb_duration)); 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 && if (beacon->lcb_sub_command != LPFC_LCB_ON &&
beacon->lcb_sub_command != LPFC_LCB_OFF) { beacon->lcb_sub_command != LPFC_LCB_OFF) {
rjt_err = LSRJT_CMD_UNSUPPORTED; rjt_err = LSRJT_CMD_UNSUPPORTED;
goto rjt; 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; rjt_err = LSRJT_CMD_UNSUPPORTED;
goto rjt; 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; state = (beacon->lcb_sub_command == LPFC_LCB_ON) ? 1 : 0;
lcb_context->sub_command = beacon->lcb_sub_command; lcb_context->sub_command = beacon->lcb_sub_command;
lcb_context->capability = 0;
lcb_context->type = beacon->lcb_type; lcb_context->type = beacon->lcb_type;
lcb_context->frequency = beacon->lcb_frequency; lcb_context->frequency = beacon->lcb_frequency;
lcb_context->duration = beacon->lcb_duration;
lcb_context->ox_id = cmdiocb->iocb.unsli3.rcvsli3.ox_id; lcb_context->ox_id = cmdiocb->iocb.unsli3.rcvsli3.ox_id;
lcb_context->rx_id = cmdiocb->iocb.ulpContext; lcb_context->rx_id = cmdiocb->iocb.ulpContext;
lcb_context->ndlp = lpfc_nlp_get(ndlp); lcb_context->ndlp = lpfc_nlp_get(ndlp);

View File

@ -1065,14 +1065,17 @@ typedef struct _ELS_PKT { /* Structure is in Big Endian format */
struct fc_lcb_request_frame { struct fc_lcb_request_frame {
uint32_t lcb_command; /* ELS command opcode (0x81) */ uint32_t lcb_command; /* ELS command opcode (0x81) */
uint8_t lcb_sub_command;/* LCB Payload Word 1, bit 24:31 */ uint8_t lcb_sub_command;/* LCB Payload Word 1, bit 24:31 */
#define LPFC_LCB_ON 0x1 #define LPFC_LCB_ON 0x1
#define LPFC_LCB_OFF 0x2 #define LPFC_LCB_OFF 0x2
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_type; /* LCB Payload Word 2, bit 24:31 */
#define LPFC_LCB_GREEN 0x1 #define LPFC_LCB_GREEN 0x1
#define LPFC_LCB_AMBER 0x2 #define LPFC_LCB_AMBER 0x2
uint8_t lcb_frequency; /* LCB Payload Word 2, bit 16:23 */ 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 */ 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 { struct fc_lcb_res_frame {
uint32_t lcb_ls_acc; /* Acceptance of LCB request (0x02) */ uint32_t lcb_ls_acc; /* Acceptance of LCB request (0x02) */
uint8_t lcb_sub_command;/* LCB Payload Word 1, bit 24:31 */ 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_type; /* LCB Payload Word 2, bit 24:31 */
uint8_t lcb_frequency; /* LCB Payload Word 2, bit 16:23 */ uint8_t lcb_frequency; /* LCB Payload Word 2, bit 16:23 */
uint16_t lcb_duration; /* LCB Payload Word 2, bit 15:0 */ uint16_t lcb_duration; /* LCB Payload Word 2, bit 15:0 */

View 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_SHIFT 16
#define lpfc_mbx_set_beacon_duration_MASK 0x000000FF #define lpfc_mbx_set_beacon_duration_MASK 0x000000FF
#define lpfc_mbx_set_beacon_duration_WORD word4 #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 /* COMMON_SET_BEACON_CONFIG_V1 */
#define lpfc_mbx_set_beacon_status_duration_WORD word4 #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 { struct lpfc_id_range {
@ -2243,6 +2246,7 @@ struct lpfc_mbx_redisc_fcf_tbl {
*/ */
#define ADD_STATUS_OPERATION_ALREADY_ACTIVE 0x67 #define ADD_STATUS_OPERATION_ALREADY_ACTIVE 0x67
#define ADD_STATUS_FW_NOT_SUPPORTED 0xEB #define ADD_STATUS_FW_NOT_SUPPORTED 0xEB
#define ADD_STATUS_INVALID_REQUEST 0x4B
struct lpfc_mbx_sli4_config { struct lpfc_mbx_sli4_config {
struct mbox_header header; struct mbox_header header;
@ -3392,7 +3396,41 @@ struct lpfc_sli4_parameters {
#define cfg_nosr_SHIFT 9 #define cfg_nosr_SHIFT 9
#define cfg_nosr_MASK 0x00000001 #define cfg_nosr_MASK 0x00000001
#define cfg_nosr_WORD word19 #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 #define LPFC_SET_UE_RECOVERY 0x10

View 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->eqav = bf_get(cfg_eqav, mbx_sli4_parameters);
sli4_params->cqav = bf_get(cfg_cqav, 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->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, sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt,
mbx_sli4_parameters); mbx_sli4_parameters);
sli4_params->wqpcnt = bf_get(cfg_wqpcnt, mbx_sli4_parameters); sli4_params->wqpcnt = bf_get(cfg_wqpcnt, mbx_sli4_parameters);

View File

@ -490,6 +490,7 @@ struct lpfc_pc_sli4_params {
uint8_t eqav; uint8_t eqav;
uint8_t cqav; uint8_t cqav;
uint8_t wqsize; uint8_t wqsize;
uint8_t bv1s;
#define LPFC_WQ_SZ64_SUPPORT 1 #define LPFC_WQ_SZ64_SUPPORT 1
#define LPFC_WQ_SZ128_SUPPORT 2 #define LPFC_WQ_SZ128_SUPPORT 2
uint8_t wqpcnt; uint8_t wqpcnt;
@ -774,7 +775,9 @@ struct lpfc_rdp_context {
struct lpfc_lcb_context { struct lpfc_lcb_context {
uint8_t sub_command; uint8_t sub_command;
uint8_t type; uint8_t type;
uint8_t capability;
uint8_t frequency; uint8_t frequency;
uint16_t duration;
uint16_t ox_id; uint16_t ox_id;
uint16_t rx_id; uint16_t rx_id;
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp;