Commit fedd3b7b authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.3.21: Critical Errors and Bug Fixes

Critical Errors:
- Correctly handle non-zero return lpfc_workq_post_event and return ENOMEM
- Save the irq level when locking the host_lock in lpfc_findnode_did

Bug Fixes:
- Adjust payload_length and request_length for sli4_config mailbox commands.
- Add the freed sgl/XRI to the tail of the list rather than to the head.
- Set the FC_VPORT_NEEDS_INIT_VPI on vport deletes and check it before
  issuing a fdisc on an els retry.
- Only call lpfc_hba_init_link() if phba->cfg_suppress_link_up
  is LPFC_INITIALIZE_LINK.
- Add support for SLI-4 Performance Hints
Signed-off-by: default avatarAlex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 382be668
...@@ -548,6 +548,8 @@ struct lpfc_hba { ...@@ -548,6 +548,8 @@ struct lpfc_hba {
#define LPFC_SLI3_CRP_ENABLED 0x08 #define LPFC_SLI3_CRP_ENABLED 0x08
#define LPFC_SLI3_BG_ENABLED 0x20 #define LPFC_SLI3_BG_ENABLED 0x20
#define LPFC_SLI3_DSS_ENABLED 0x40 #define LPFC_SLI3_DSS_ENABLED 0x40
#define LPFC_SLI4_PERFH_ENABLED 0x80
#define LPFC_SLI4_PHWQ_ENABLED 0x100
uint32_t iocb_cmd_size; uint32_t iocb_cmd_size;
uint32_t iocb_rsp_size; uint32_t iocb_rsp_size;
......
...@@ -623,10 +623,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) ...@@ -623,10 +623,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
int status = 0; int status = 0;
int cnt = 0; int cnt = 0;
int i; int i;
int rc;
init_completion(&online_compl); init_completion(&online_compl);
lpfc_workq_post_event(phba, &status, &online_compl, rc = lpfc_workq_post_event(phba, &status, &online_compl,
LPFC_EVT_OFFLINE_PREP); LPFC_EVT_OFFLINE_PREP);
if (rc == 0)
return -ENOMEM;
wait_for_completion(&online_compl); wait_for_completion(&online_compl);
if (status != 0) if (status != 0)
...@@ -652,7 +656,10 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) ...@@ -652,7 +656,10 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
} }
init_completion(&online_compl); init_completion(&online_compl);
lpfc_workq_post_event(phba, &status, &online_compl, type); rc = lpfc_workq_post_event(phba, &status, &online_compl, type);
if (rc == 0)
return -ENOMEM;
wait_for_completion(&online_compl); wait_for_completion(&online_compl);
if (status != 0) if (status != 0)
...@@ -682,6 +689,7 @@ lpfc_selective_reset(struct lpfc_hba *phba) ...@@ -682,6 +689,7 @@ lpfc_selective_reset(struct lpfc_hba *phba)
{ {
struct completion online_compl; struct completion online_compl;
int status = 0; int status = 0;
int rc;
if (!phba->cfg_enable_hba_reset) if (!phba->cfg_enable_hba_reset)
return -EIO; return -EIO;
...@@ -692,8 +700,11 @@ lpfc_selective_reset(struct lpfc_hba *phba) ...@@ -692,8 +700,11 @@ lpfc_selective_reset(struct lpfc_hba *phba)
return status; return status;
init_completion(&online_compl); init_completion(&online_compl);
lpfc_workq_post_event(phba, &status, &online_compl, rc = lpfc_workq_post_event(phba, &status, &online_compl,
LPFC_EVT_ONLINE); LPFC_EVT_ONLINE);
if (rc == 0)
return -ENOMEM;
wait_for_completion(&online_compl); wait_for_completion(&online_compl);
if (status != 0) if (status != 0)
...@@ -812,14 +823,17 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, ...@@ -812,14 +823,17 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
struct completion online_compl; struct completion online_compl;
int status=0; int status=0;
int rc;
if (!phba->cfg_enable_hba_reset) if (!phba->cfg_enable_hba_reset)
return -EACCES; return -EACCES;
init_completion(&online_compl); init_completion(&online_compl);
if(strncmp(buf, "online", sizeof("online") - 1) == 0) { if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
lpfc_workq_post_event(phba, &status, &online_compl, rc = lpfc_workq_post_event(phba, &status, &online_compl,
LPFC_EVT_ONLINE); LPFC_EVT_ONLINE);
if (rc == 0)
return -ENOMEM;
wait_for_completion(&online_compl); wait_for_completion(&online_compl);
} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
...@@ -1813,6 +1827,7 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, ...@@ -1813,6 +1827,7 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
int stat1=0, stat2=0; int stat1=0, stat2=0;
unsigned int i, j, cnt=count; unsigned int i, j, cnt=count;
u8 wwpn[8]; u8 wwpn[8];
int rc;
if (!phba->cfg_enable_hba_reset) if (!phba->cfg_enable_hba_reset)
return -EACCES; return -EACCES;
...@@ -1863,7 +1878,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, ...@@ -1863,7 +1878,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
"0463 lpfc_soft_wwpn attribute set failed to " "0463 lpfc_soft_wwpn attribute set failed to "
"reinit adapter - %d\n", stat1); "reinit adapter - %d\n", stat1);
init_completion(&online_compl); init_completion(&online_compl);
lpfc_workq_post_event(phba, &stat2, &online_compl, LPFC_EVT_ONLINE); rc = lpfc_workq_post_event(phba, &stat2, &online_compl,
LPFC_EVT_ONLINE);
if (rc == 0)
return -ENOMEM;
wait_for_completion(&online_compl); wait_for_completion(&online_compl);
if (stat2) if (stat2)
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
......
...@@ -53,9 +53,9 @@ void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *); ...@@ -53,9 +53,9 @@ void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *); void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *);
void lpfc_supported_pages(struct lpfcMboxq *); void lpfc_supported_pages(struct lpfcMboxq *);
void lpfc_sli4_params(struct lpfcMboxq *); void lpfc_pc_sli4_params(struct lpfcMboxq *);
int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *);
struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
void lpfc_cleanup_rcv_buffers(struct lpfc_vport *); void lpfc_cleanup_rcv_buffers(struct lpfc_vport *);
void lpfc_rcv_seq_check_edtov(struct lpfc_vport *); void lpfc_rcv_seq_check_edtov(struct lpfc_vport *);
......
...@@ -2745,7 +2745,8 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) ...@@ -2745,7 +2745,8 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
} }
break; break;
case ELS_CMD_FDISC: case ELS_CMD_FDISC:
lpfc_issue_els_fdisc(vport, ndlp, retry); if (!(vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI))
lpfc_issue_els_fdisc(vport, ndlp, retry);
break; break;
} }
return; return;
......
...@@ -4426,10 +4426,11 @@ lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) ...@@ -4426,10 +4426,11 @@ lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp;
unsigned long iflags;
spin_lock_irq(shost->host_lock); spin_lock_irqsave(shost->host_lock, iflags);
ndlp = __lpfc_findnode_did(vport, did); ndlp = __lpfc_findnode_did(vport, did);
spin_unlock_irq(shost->host_lock); spin_unlock_irqrestore(shost->host_lock, iflags);
return ndlp; return ndlp;
} }
......
...@@ -778,6 +778,7 @@ struct mbox_header { ...@@ -778,6 +778,7 @@ struct mbox_header {
#define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A #define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A
#define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D #define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D
#define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A
#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5
/* FCoE Opcodes */ /* FCoE Opcodes */
#define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE 0x01 #define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE 0x01
...@@ -1852,6 +1853,9 @@ struct lpfc_mbx_request_features { ...@@ -1852,6 +1853,9 @@ struct lpfc_mbx_request_features {
#define lpfc_mbx_rq_ftr_rq_ifip_SHIFT 7 #define lpfc_mbx_rq_ftr_rq_ifip_SHIFT 7
#define lpfc_mbx_rq_ftr_rq_ifip_MASK 0x00000001 #define lpfc_mbx_rq_ftr_rq_ifip_MASK 0x00000001
#define lpfc_mbx_rq_ftr_rq_ifip_WORD word2 #define lpfc_mbx_rq_ftr_rq_ifip_WORD word2
#define lpfc_mbx_rq_ftr_rq_perfh_SHIFT 11
#define lpfc_mbx_rq_ftr_rq_perfh_MASK 0x00000001
#define lpfc_mbx_rq_ftr_rq_perfh_WORD word2
uint32_t word3; uint32_t word3;
#define lpfc_mbx_rq_ftr_rsp_iaab_SHIFT 0 #define lpfc_mbx_rq_ftr_rsp_iaab_SHIFT 0
#define lpfc_mbx_rq_ftr_rsp_iaab_MASK 0x00000001 #define lpfc_mbx_rq_ftr_rsp_iaab_MASK 0x00000001
...@@ -1877,6 +1881,9 @@ struct lpfc_mbx_request_features { ...@@ -1877,6 +1881,9 @@ struct lpfc_mbx_request_features {
#define lpfc_mbx_rq_ftr_rsp_ifip_SHIFT 7 #define lpfc_mbx_rq_ftr_rsp_ifip_SHIFT 7
#define lpfc_mbx_rq_ftr_rsp_ifip_MASK 0x00000001 #define lpfc_mbx_rq_ftr_rsp_ifip_MASK 0x00000001
#define lpfc_mbx_rq_ftr_rsp_ifip_WORD word3 #define lpfc_mbx_rq_ftr_rsp_ifip_WORD word3
#define lpfc_mbx_rq_ftr_rsp_perfh_SHIFT 11
#define lpfc_mbx_rq_ftr_rsp_perfh_MASK 0x00000001
#define lpfc_mbx_rq_ftr_rsp_perfh_WORD word3
}; };
struct lpfc_mbx_supp_pages { struct lpfc_mbx_supp_pages {
...@@ -1935,7 +1942,7 @@ struct lpfc_mbx_supp_pages { ...@@ -1935,7 +1942,7 @@ struct lpfc_mbx_supp_pages {
#define LPFC_SLI4_PARAMETERS 2 #define LPFC_SLI4_PARAMETERS 2
}; };
struct lpfc_mbx_sli4_params { struct lpfc_mbx_pc_sli4_params {
uint32_t word1; uint32_t word1;
#define qs_SHIFT 0 #define qs_SHIFT 0
#define qs_MASK 0x00000001 #define qs_MASK 0x00000001
...@@ -2051,6 +2058,88 @@ struct lpfc_mbx_sli4_params { ...@@ -2051,6 +2058,88 @@ struct lpfc_mbx_sli4_params {
uint32_t rsvd_13_63[51]; uint32_t rsvd_13_63[51];
}; };
struct lpfc_sli4_parameters {
uint32_t word0;
#define cfg_prot_type_SHIFT 0
#define cfg_prot_type_MASK 0x000000FF
#define cfg_prot_type_WORD word0
uint32_t word1;
#define cfg_ft_SHIFT 0
#define cfg_ft_MASK 0x00000001
#define cfg_ft_WORD word1
#define cfg_sli_rev_SHIFT 4
#define cfg_sli_rev_MASK 0x0000000f
#define cfg_sli_rev_WORD word1
#define cfg_sli_family_SHIFT 8
#define cfg_sli_family_MASK 0x0000000f
#define cfg_sli_family_WORD word1
#define cfg_if_type_SHIFT 12
#define cfg_if_type_MASK 0x0000000f
#define cfg_if_type_WORD word1
#define cfg_sli_hint_1_SHIFT 16
#define cfg_sli_hint_1_MASK 0x000000ff
#define cfg_sli_hint_1_WORD word1
#define cfg_sli_hint_2_SHIFT 24
#define cfg_sli_hint_2_MASK 0x0000001f
#define cfg_sli_hint_2_WORD word1
uint32_t word2;
uint32_t word3;
uint32_t word4;
#define cfg_cqv_SHIFT 14
#define cfg_cqv_MASK 0x00000003
#define cfg_cqv_WORD word4
uint32_t word5;
uint32_t word6;
#define cfg_mqv_SHIFT 14
#define cfg_mqv_MASK 0x00000003
#define cfg_mqv_WORD word6
uint32_t word7;
uint32_t word8;
#define cfg_wqv_SHIFT 14
#define cfg_wqv_MASK 0x00000003
#define cfg_wqv_WORD word8
uint32_t word9;
uint32_t word10;
#define cfg_rqv_SHIFT 14
#define cfg_rqv_MASK 0x00000003
#define cfg_rqv_WORD word10
uint32_t word11;
#define cfg_rq_db_window_SHIFT 28
#define cfg_rq_db_window_MASK 0x0000000f
#define cfg_rq_db_window_WORD word11
uint32_t word12;
#define cfg_fcoe_SHIFT 0
#define cfg_fcoe_MASK 0x00000001
#define cfg_fcoe_WORD word12
#define cfg_phwq_SHIFT 15
#define cfg_phwq_MASK 0x00000001
#define cfg_phwq_WORD word12
#define cfg_loopbk_scope_SHIFT 28
#define cfg_loopbk_scope_MASK 0x0000000f
#define cfg_loopbk_scope_WORD word12
uint32_t sge_supp_len;
uint32_t word14;
#define cfg_sgl_page_cnt_SHIFT 0
#define cfg_sgl_page_cnt_MASK 0x0000000f
#define cfg_sgl_page_cnt_WORD word14
#define cfg_sgl_page_size_SHIFT 8
#define cfg_sgl_page_size_MASK 0x000000ff
#define cfg_sgl_page_size_WORD word14
#define cfg_sgl_pp_align_SHIFT 16
#define cfg_sgl_pp_align_MASK 0x000000ff
#define cfg_sgl_pp_align_WORD word14
uint32_t word15;
uint32_t word16;
uint32_t word17;
uint32_t word18;
uint32_t word19;
};
struct lpfc_mbx_get_sli4_parameters {
struct mbox_header header;
struct lpfc_sli4_parameters sli4_parameters;
};
/* Mailbox Completion Queue Error Messages */ /* Mailbox Completion Queue Error Messages */
#define MB_CQE_STATUS_SUCCESS 0x0 #define MB_CQE_STATUS_SUCCESS 0x0
#define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1 #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1
...@@ -2103,7 +2192,8 @@ struct lpfc_mqe { ...@@ -2103,7 +2192,8 @@ struct lpfc_mqe {
struct lpfc_mbx_post_hdr_tmpl hdr_tmpl; struct lpfc_mbx_post_hdr_tmpl hdr_tmpl;
struct lpfc_mbx_query_fw_cfg query_fw_cfg; struct lpfc_mbx_query_fw_cfg query_fw_cfg;
struct lpfc_mbx_supp_pages supp_pages; struct lpfc_mbx_supp_pages supp_pages;
struct lpfc_mbx_sli4_params sli4_params; struct lpfc_mbx_pc_sli4_params sli4_params;
struct lpfc_mbx_get_sli4_parameters get_sli4_parameters;
struct lpfc_mbx_nop nop; struct lpfc_mbx_nop nop;
} un; } un;
}; };
...@@ -2381,6 +2471,10 @@ struct wqe_common { ...@@ -2381,6 +2471,10 @@ struct wqe_common {
#define wqe_wqes_SHIFT 15 #define wqe_wqes_SHIFT 15
#define wqe_wqes_MASK 0x00000001 #define wqe_wqes_MASK 0x00000001
#define wqe_wqes_WORD word10 #define wqe_wqes_WORD word10
/* Note that this field overlaps above fields */
#define wqe_wqid_SHIFT 1
#define wqe_wqid_MASK 0x0000007f
#define wqe_wqid_WORD word10
#define wqe_pri_SHIFT 16 #define wqe_pri_SHIFT 16
#define wqe_pri_MASK 0x00000007 #define wqe_pri_MASK 0x00000007
#define wqe_pri_WORD word10 #define wqe_pri_WORD word10
...@@ -2599,7 +2693,8 @@ struct fcp_iwrite64_wqe { ...@@ -2599,7 +2693,8 @@ struct fcp_iwrite64_wqe {
uint32_t total_xfer_len; uint32_t total_xfer_len;
uint32_t initial_xfer_len; uint32_t initial_xfer_len;
struct wqe_common wqe_com; /* words 6-11 */ struct wqe_common wqe_com; /* words 6-11 */
uint32_t rsvd_12_15[4]; /* word 12-15 */ uint32_t rsrvd12;
struct ulp_bde64 ph_bde; /* words 13-15 */
}; };
struct fcp_iread64_wqe { struct fcp_iread64_wqe {
...@@ -2608,7 +2703,8 @@ struct fcp_iread64_wqe { ...@@ -2608,7 +2703,8 @@ struct fcp_iread64_wqe {
uint32_t total_xfer_len; /* word 4 */ uint32_t total_xfer_len; /* word 4 */
uint32_t rsrvd5; /* word 5 */ uint32_t rsrvd5; /* word 5 */
struct wqe_common wqe_com; /* words 6-11 */ struct wqe_common wqe_com; /* words 6-11 */
uint32_t rsvd_12_15[4]; /* word 12-15 */ uint32_t rsrvd12;
struct ulp_bde64 ph_bde; /* words 13-15 */
}; };
struct fcp_icmnd64_wqe { struct fcp_icmnd64_wqe {
......
...@@ -4283,36 +4283,37 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) ...@@ -4283,36 +4283,37 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
goto out_free_bsmbx; goto out_free_bsmbx;
} }
/* Get the Supported Pages. It is always available. */ /* Get the Supported Pages if PORT_CAPABILITIES is supported by port. */
lpfc_supported_pages(mboxq); lpfc_supported_pages(mboxq);
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
if (unlikely(rc)) { if (!rc) {
rc = -EIO; mqe = &mboxq->u.mqe;
mempool_free(mboxq, phba->mbox_mem_pool); memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3),
goto out_free_bsmbx; LPFC_MAX_SUPPORTED_PAGES);
} for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) {
switch (pn_page[i]) {
mqe = &mboxq->u.mqe; case LPFC_SLI4_PARAMETERS:
memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3), phba->sli4_hba.pc_sli4_params.supported = 1;
LPFC_MAX_SUPPORTED_PAGES); break;
for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) { default:
switch (pn_page[i]) { break;
case LPFC_SLI4_PARAMETERS: }
phba->sli4_hba.pc_sli4_params.supported = 1; }
break; /* Read the port's SLI4 Parameters capabilities if supported. */
default: if (phba->sli4_hba.pc_sli4_params.supported)
break; rc = lpfc_pc_sli4_params_get(phba, mboxq);
if (rc) {
mempool_free(mboxq, phba->mbox_mem_pool);
rc = -EIO;
goto out_free_bsmbx;
} }
} }
/*
/* Read the port's SLI4 Parameters capabilities if supported. */ * Get sli4 parameters that override parameters from Port capabilities.
if (phba->sli4_hba.pc_sli4_params.supported) * If this call fails it is not a critical error so continue loading.
rc = lpfc_pc_sli4_params_get(phba, mboxq); */
lpfc_get_sli4_parameters(phba, mboxq);
mempool_free(mboxq, phba->mbox_mem_pool); mempool_free(mboxq, phba->mbox_mem_pool);
if (rc) {
rc = -EIO;
goto out_free_bsmbx;
}
/* Create all the SLI4 queues */ /* Create all the SLI4 queues */
rc = lpfc_sli4_queue_create(phba); rc = lpfc_sli4_queue_create(phba);
if (rc) if (rc)
...@@ -7810,7 +7811,7 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) ...@@ -7810,7 +7811,7 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
mqe = &mboxq->u.mqe; mqe = &mboxq->u.mqe;
/* Read the port's SLI4 Parameters port capabilities */ /* Read the port's SLI4 Parameters port capabilities */
lpfc_sli4_params(mboxq); lpfc_pc_sli4_params(mboxq);
if (!phba->sli4_hba.intr_enable) if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
else { else {
...@@ -7853,6 +7854,66 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) ...@@ -7853,6 +7854,66 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
return rc; return rc;
} }
/**
* lpfc_get_sli4_parameters - Get the SLI4 Config PARAMETERS.
* @phba: Pointer to HBA context object.
* @mboxq: Pointer to the mailboxq memory for the mailbox command response.
*
* This function is called in the SLI4 code path to read the port's
* sli4 capabilities.
*
* This function may be be called from any context that can block-wait
* for the completion. The expectation is that this routine is called
* typically from probe_one or from the online routine.
**/
int
lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
int rc;
struct lpfc_mqe *mqe = &mboxq->u.mqe;
struct lpfc_pc_sli4_params *sli4_params;
int length;
struct lpfc_sli4_parameters *mbx_sli4_parameters;
/* Read the port's SLI4 Config Parameters */
length = (sizeof(struct lpfc_mbx_get_sli4_parameters) -
sizeof(struct lpfc_sli4_cfg_mhdr));
lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS,
length, LPFC_SLI4_MBX_EMBED);
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
else
rc = lpfc_sli_issue_mbox_wait(phba, mboxq,
lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG));
if (unlikely(rc))
return rc;
sli4_params = &phba->sli4_hba.pc_sli4_params;
mbx_sli4_parameters = &mqe->un.get_sli4_parameters.sli4_parameters;
sli4_params->if_type = bf_get(cfg_if_type, mbx_sli4_parameters);
sli4_params->sli_rev = bf_get(cfg_sli_rev, mbx_sli4_parameters);
sli4_params->sli_family = bf_get(cfg_sli_family, mbx_sli4_parameters);
sli4_params->featurelevel_1 = bf_get(cfg_sli_hint_1,
mbx_sli4_parameters);
sli4_params->featurelevel_2 = bf_get(cfg_sli_hint_2,
mbx_sli4_parameters);
if (bf_get(cfg_phwq, mbx_sli4_parameters))
phba->sli3_options |= LPFC_SLI4_PHWQ_ENABLED;
else
phba->sli3_options &= ~LPFC_SLI4_PHWQ_ENABLED;
sli4_params->sge_supp_len = mbx_sli4_parameters->sge_supp_len;
sli4_params->loopbk_scope = bf_get(loopbk_scope, mbx_sli4_parameters);
sli4_params->cqv = bf_get(cfg_cqv, mbx_sli4_parameters);
sli4_params->mqv = bf_get(cfg_mqv, mbx_sli4_parameters);
sli4_params->wqv = bf_get(cfg_wqv, mbx_sli4_parameters);
sli4_params->rqv = bf_get(cfg_rqv, mbx_sli4_parameters);
sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt,
mbx_sli4_parameters);
sli4_params->sgl_pp_align = bf_get(cfg_sgl_pp_align,
mbx_sli4_parameters);
return 0;
}
/** /**
* lpfc_pci_probe_one_s3 - PCI probe func to reg SLI-3 device to PCI subsystem. * lpfc_pci_probe_one_s3 - PCI probe func to reg SLI-3 device to PCI subsystem.
* @pdev: pointer to PCI device * @pdev: pointer to PCI device
......
...@@ -1692,7 +1692,7 @@ lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox) ...@@ -1692,7 +1692,7 @@ lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
* @mbox: pointer to lpfc mbox command. * @mbox: pointer to lpfc mbox command.
* @subsystem: The sli4 config sub mailbox subsystem. * @subsystem: The sli4 config sub mailbox subsystem.
* @opcode: The sli4 config sub mailbox command opcode. * @opcode: The sli4 config sub mailbox command opcode.
* @length: Length of the sli4 config mailbox command. * @length: Length of the sli4 config mailbox command (including sub-header).
* *
* This routine sets up the header fields of SLI4 specific mailbox command * This routine sets up the header fields of SLI4 specific mailbox command
* for sending IOCTL command. * for sending IOCTL command.
...@@ -1723,14 +1723,14 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, ...@@ -1723,14 +1723,14 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
if (emb) { if (emb) {
/* Set up main header fields */ /* Set up main header fields */
bf_set(lpfc_mbox_hdr_emb, &sli4_config->header.cfg_mhdr, 1); bf_set(lpfc_mbox_hdr_emb, &sli4_config->header.cfg_mhdr, 1);
sli4_config->header.cfg_mhdr.payload_length = sli4_config->header.cfg_mhdr.payload_length = length;
LPFC_MBX_CMD_HDR_LENGTH + length;
/* Set up sub-header fields following main header */ /* Set up sub-header fields following main header */
bf_set(lpfc_mbox_hdr_opcode, bf_set(lpfc_mbox_hdr_opcode,
&sli4_config->header.cfg_shdr.request, opcode); &sli4_config->header.cfg_shdr.request, opcode);
bf_set(lpfc_mbox_hdr_subsystem, bf_set(lpfc_mbox_hdr_subsystem,
&sli4_config->header.cfg_shdr.request, subsystem); &sli4_config->header.cfg_shdr.request, subsystem);
sli4_config->header.cfg_shdr.request.request_length = length; sli4_config->header.cfg_shdr.request.request_length =
length - LPFC_MBX_CMD_HDR_LENGTH;
return length; return length;
} }
...@@ -1902,6 +1902,7 @@ lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq) ...@@ -1902,6 +1902,7 @@ lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq)
/* Set up host requested features. */ /* Set up host requested features. */
bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1); bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1);
bf_set(lpfc_mbx_rq_ftr_rq_perfh, &mboxq->u.mqe.un.req_ftrs, 1);
/* Enable DIF (block guard) only if configured to do so. */ /* Enable DIF (block guard) only if configured to do so. */
if (phba->cfg_enable_bg) if (phba->cfg_enable_bg)
...@@ -2159,17 +2160,16 @@ lpfc_supported_pages(struct lpfcMboxq *mbox) ...@@ -2159,17 +2160,16 @@ lpfc_supported_pages(struct lpfcMboxq *mbox)
} }
/** /**
* lpfc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params * lpfc_pc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params mbox cmd.
* mailbox command.
* @mbox: pointer to lpfc mbox command to initialize. * @mbox: pointer to lpfc mbox command to initialize.
* *
* The PORT_CAPABILITIES SLI4 parameters mailbox command is issued to * The PORT_CAPABILITIES SLI4 parameters mailbox command is issued to
* retrieve the particular SLI4 features supported by the port. * retrieve the particular SLI4 features supported by the port.
**/ **/
void void
lpfc_sli4_params(struct lpfcMboxq *mbox) lpfc_pc_sli4_params(struct lpfcMboxq *mbox)
{ {
struct lpfc_mbx_sli4_params *sli4_params; struct lpfc_mbx_pc_sli4_params *sli4_params;
memset(mbox, 0, sizeof(*mbox)); memset(mbox, 0, sizeof(*mbox));
sli4_params = &mbox->u.mqe.un.sli4_params; sli4_params = &mbox->u.mqe.un.sli4_params;
......
...@@ -1981,12 +1981,14 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) ...@@ -1981,12 +1981,14 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
struct scatterlist *sgel = NULL; struct scatterlist *sgel = NULL;
struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl; struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl;
struct sli4_sge *first_data_sgl;
IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
dma_addr_t physaddr; dma_addr_t physaddr;
uint32_t num_bde = 0; uint32_t num_bde = 0;
uint32_t dma_len; uint32_t dma_len;
uint32_t dma_offset = 0; uint32_t dma_offset = 0;
int nseg; int nseg;
struct ulp_bde64 *bde;
/* /*
* There are three possibilities here - use scatter-gather segment, use * There are three possibilities here - use scatter-gather segment, use
...@@ -2011,7 +2013,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) ...@@ -2011,7 +2013,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
bf_set(lpfc_sli4_sge_last, sgl, 0); bf_set(lpfc_sli4_sge_last, sgl, 0);
sgl->word2 = cpu_to_le32(sgl->word2); sgl->word2 = cpu_to_le32(sgl->word2);
sgl += 1; sgl += 1;
first_data_sgl = sgl;
lpfc_cmd->seg_cnt = nseg; lpfc_cmd->seg_cnt = nseg;
if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:" lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:"
...@@ -2047,6 +2049,17 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) ...@@ -2047,6 +2049,17 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
dma_offset += dma_len; dma_offset += dma_len;
sgl++; sgl++;
} }
/* setup the performance hint (first data BDE) if enabled */
if (phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) {
bde = (struct ulp_bde64 *)
&(iocb_cmd->unsli3.sli3Words[5]);
bde->addrLow = first_data_sgl->addr_lo;
bde->addrHigh = first_data_sgl->addr_hi;
bde->tus.f.bdeSize =
le32_to_cpu(first_data_sgl->sge_len);
bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
bde->tus.w = cpu_to_le32(bde->tus.w);
}
} else { } else {
sgl += 1; sgl += 1;
/* clear the last flag in the fcp_rsp map entry */ /* clear the last flag in the fcp_rsp map entry */
......
...@@ -96,7 +96,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) ...@@ -96,7 +96,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe)
/* set consumption flag every once in a while */ /* set consumption flag every once in a while */
if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL)) if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL))
bf_set(wqe_wqec, &wqe->generic.wqe_com, 1); bf_set(wqe_wqec, &wqe->generic.wqe_com, 1);
if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id);
lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
/* Update the host index before invoking device */ /* Update the host index before invoking device */
...@@ -969,7 +970,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) ...@@ -969,7 +970,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
} else { } else {
sglq->state = SGL_FREED; sglq->state = SGL_FREED;
sglq->ndlp = NULL; sglq->ndlp = NULL;
list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); list_add_tail(&sglq->list,
&phba->sli4_hba.lpfc_sgl_list);
/* Check if TXQ queue needs to be serviced */ /* Check if TXQ queue needs to be serviced */
if (pring->txq_cnt) if (pring->txq_cnt)
...@@ -4817,7 +4819,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) ...@@ -4817,7 +4819,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
"0378 No support for fcpi mode.\n"); "0378 No support for fcpi mode.\n");
ftr_rsp++; ftr_rsp++;
} }
if (bf_get(lpfc_mbx_rq_ftr_rsp_perfh, &mqe->un.req_ftrs))
phba->sli3_options |= LPFC_SLI4_PERFH_ENABLED;
else
phba->sli3_options &= ~LPFC_SLI4_PERFH_ENABLED;
/* /*
* If the port cannot support the host's requested features * If the port cannot support the host's requested features
* then turn off the global config parameters to disable the * then turn off the global config parameters to disable the
...@@ -5004,7 +5009,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) ...@@ -5004,7 +5009,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
phba->link_state = LPFC_LINK_DOWN; phba->link_state = LPFC_LINK_DOWN;
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK)
rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
out_unset_queue: out_unset_queue:
/* Unset all the queues set up in this routine when error out */ /* Unset all the queues set up in this routine when error out */
if (rc) if (rc)
...@@ -11189,7 +11195,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq, ...@@ -11189,7 +11195,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq,
if (!mbox) if (!mbox)
return -ENOMEM; return -ENOMEM;
length = (sizeof(struct lpfc_mbx_rq_destroy) - length = (sizeof(struct lpfc_mbx_rq_destroy) -
sizeof(struct mbox_header)); sizeof(struct lpfc_sli4_cfg_mhdr));
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
LPFC_MBOX_OPCODE_FCOE_RQ_DESTROY, LPFC_MBOX_OPCODE_FCOE_RQ_DESTROY,
length, LPFC_SLI4_MBX_EMBED); length, LPFC_SLI4_MBX_EMBED);
...@@ -11279,7 +11285,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, ...@@ -11279,7 +11285,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba,
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES, LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES,
sizeof(struct lpfc_mbx_post_sgl_pages) - sizeof(struct lpfc_mbx_post_sgl_pages) -
sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED); sizeof(struct lpfc_sli4_cfg_mhdr), LPFC_SLI4_MBX_EMBED);
post_sgl_pages = (struct lpfc_mbx_post_sgl_pages *) post_sgl_pages = (struct lpfc_mbx_post_sgl_pages *)
&mbox->u.mqe.un.post_sgl_pages; &mbox->u.mqe.un.post_sgl_pages;
...@@ -12402,7 +12408,8 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) ...@@ -12402,7 +12408,8 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE, LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE,
sizeof(struct lpfc_mbx_post_hdr_tmpl) - sizeof(struct lpfc_mbx_post_hdr_tmpl) -
sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED); sizeof(struct lpfc_sli4_cfg_mhdr),
LPFC_SLI4_MBX_EMBED);
bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt, bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt,
hdr_tmpl, rpi_page->page_count); hdr_tmpl, rpi_page->page_count);
bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl, bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl,
......
...@@ -359,6 +359,10 @@ struct lpfc_pc_sli4_params { ...@@ -359,6 +359,10 @@ struct lpfc_pc_sli4_params {
uint32_t hdr_pp_align; uint32_t hdr_pp_align;
uint32_t sgl_pages_max; uint32_t sgl_pages_max;
uint32_t sgl_pp_align; uint32_t sgl_pp_align;
uint8_t cqv;
uint8_t mqv;
uint8_t wqv;
uint8_t rqv;
}; };
/* SLI4 HBA data structure entries */ /* SLI4 HBA data structure entries */
......
...@@ -464,6 +464,7 @@ disable_vport(struct fc_vport *fc_vport) ...@@ -464,6 +464,7 @@ disable_vport(struct fc_vport *fc_vport)
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL; struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
long timeout; long timeout;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
ndlp = lpfc_findnode_did(vport, Fabric_DID); ndlp = lpfc_findnode_did(vport, Fabric_DID);
if (ndlp && NLP_CHK_NODE_ACT(ndlp) if (ndlp && NLP_CHK_NODE_ACT(ndlp)
...@@ -498,6 +499,9 @@ disable_vport(struct fc_vport *fc_vport) ...@@ -498,6 +499,9 @@ disable_vport(struct fc_vport *fc_vport)
* scsi_host_put() to release the vport. * scsi_host_put() to release the vport.
*/ */
lpfc_mbx_unreg_vpi(vport); lpfc_mbx_unreg_vpi(vport);
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
spin_unlock_irq(shost->host_lock);
lpfc_vport_set_state(vport, FC_VPORT_DISABLED); lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment