Skip to content

Commit

Permalink
scsi: lpfc: Support duration field in Link Cable Beacon V1 command
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
James Smart authored and Martin K. Petersen committed Jul 11, 2018
1 parent 414abe0 commit 66e9e6b
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 28 deletions.
64 changes: 47 additions & 17 deletions drivers/scsi/lpfc/lpfc_els.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
Expand Down
18 changes: 11 additions & 7 deletions drivers/scsi/lpfc/lpfc_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
};

Expand All @@ -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 */
Expand Down
46 changes: 42 additions & 4 deletions drivers/scsi/lpfc/lpfc_hw4.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/lpfc/lpfc_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions drivers/scsi/lpfc/lpfc_sli4.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 66e9e6b

Please sign in to comment.