lpfc 8.3.21: Critical Errors and Bug Fixes
Subsystems (2)
PATCH 1/6 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 Alex Iannicelli <[email protected]>
Signed-off-by James Smart <[email protected]>
---
lpfc.h | 2 + lpfc_attr.c | 29 ++++++++++++-- lpfc_crtn.h | 4 +- lpfc_els.c | 3 + lpfc_hbadisc.c | 5 +- lpfc_hw4.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++-- lpfc_init.c | 113 +++++++++++++++++++++++++++++++++++++++++++-------------- lpfc_mbox.c | 16 ++++---- lpfc_scsi.c | 15 +++++++ lpfc_sli.c | 21 +++++++--- lpfc_sli4.h | 4 ++ lpfc_vport.c | 4 ++ 12 files changed, 264 insertions(+), 56 deletions(-)
drivers/scsi/lpfc/lpfc_attr.c +24 -5
@@ -623,10 +623,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint status =0 ;int cnt =0 ;int i; +int rc;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 ); +if (rc ==0 ) +return -ENOMEM ; +wait_for_completion (&online_compl);if (status !=0 )
@@ -652,7 +656,10 @@ lpfc_do_offline(struct lpfc_hba *phba, u }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);if (status !=0 )
@@ -682,6 +689,7 @@ lpfc_selective_reset(struct lpfc_hba *ph {struct completion online_compl;int status =0 ; +int rc;if (!phba->cfg_enable_hba_reset)return -EIO ;
@@ -692,8 +700,11 @@ lpfc_selective_reset(struct lpfc_hba *phreturn status;init_completion (&online_compl); -lpfc_workq_post_event (phba, &status, &online_compl, + rc =lpfc_workq_post_event (phba, &status, &online_compl,LPFC_EVT_ONLINE ); +if (rc ==0 ) +return -ENOMEM ; +wait_for_completion (&online_compl);if (status !=0 )
@@ -812,14 +823,17 @@ lpfc_board_mode_store(struct device *devstruct lpfc_hba *phba = vport->phba;struct completion online_compl;int status=0 ; +int rc;if (!phba->cfg_enable_hba_reset)return -EACCES ;init_completion (&online_compl);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 ); +if (rc ==0 ) +return -ENOMEM ;wait_for_completion (&online_compl); }else if (strncmp (buf,"offline" ,sizeof ("offline" ) -1 ) ==0 ) status =lpfc_do_offline (phba,LPFC_EVT_OFFLINE );
@@ -1813,6 +1827,7 @@ lpfc_soft_wwpn_store(struct device *dev,int stat1=0 , stat2=0 ;unsigned int i, j, cnt=count;u8 wwpn[8 ]; +int rc;if (!phba->cfg_enable_hba_reset)return -EACCES ;
@@ -1863,7 +1878,11 @@ lpfc_soft_wwpn_store(struct device *dev,"0463 lpfc_soft_wwpn attribute set failed to " "reinit adapter - %d\n", stat1);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);if (stat2) lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
drivers/scsi/lpfc/lpfc_crtn.h +2 -2
@@ -53,9 +53,9 @@ void lpfc_unreg_vpi(struct lpfc_hba *, uvoid lpfc_init_link (struct lpfc_hba *,LPFC_MBOXQ_t *,uint32_t ,uint32_t );void lpfc_request_features (struct lpfc_hba *,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_get_sli4_parameters (struct lpfc_hba *,LPFC_MBOXQ_t *);struct lpfc_vport *lpfc_find_vport_by_did (struct lpfc_hba *,uint32_t );void lpfc_cleanup_rcv_buffers (struct lpfc_vport *);void lpfc_rcv_seq_check_edtov (struct lpfc_vport *);
drivers/scsi/lpfc/lpfc_els.c +2 -1
@@ -2745,7 +2745,8 @@ lpfc_els_retry_delay_handler(struct lpfc }break ;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 ; }return ;
drivers/scsi/lpfc/lpfc.h +2 -0
@@ -548,6 +548,8 @@ struct lpfc_hba {#define LPFC_SLI3_CRP_ENABLED 0x08#define LPFC_SLI3_BG_ENABLED 0x20#define LPFC_SLI3_DSS_ENABLED 0x40 +#define LPFC_SLI4_PERFH_ENABLED 0x80 +#define LPFC_SLI4_PHWQ_ENABLED 0x100uint32_t iocb_cmd_size;uint32_t iocb_rsp_size;
drivers/scsi/lpfc/lpfc_hbadisc.c +3 -2
@@ -4426,10 +4426,11 @@ lpfc_findnode_did(struct lpfc_vport *vpo {struct Scsi_Host *shost =lpfc_shost_from_vport (vport);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); -spin_unlock_irq (shost->host_lock); +spin_unlock_irqrestore (shost->host_lock, iflags);return ndlp; }
drivers/scsi/lpfc/lpfc_hw4.h +100 -4
158 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_init.c +87 -26
136 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_mbox.c +8 -8
@@ -1692,7 +1692,7 @@ lpfc_sli4_mbox_cmd_free(struct lpfc_hba* @mbox: pointer to lpfc mbox command. * @subsystem: The sli4 config sub mailbox subsystem. * @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 * for sending IOCTL command.
@@ -1723,14 +1723,14 @@ lpfc_sli4_config(struct lpfc_hba *phba,if (emb) {/* Set up main header fields */ bf_set (lpfc_mbox_hdr_emb, &sli4_config->header.cfg_mhdr,1 ); - sli4_config->header.cfg_mhdr.payload_length = -LPFC_MBX_CMD_HDR_LENGTH + length; + sli4_config->header.cfg_mhdr.payload_length = length;/* Set up sub-header fields following main header */ bf_set (lpfc_mbox_hdr_opcode, &sli4_config->header.cfg_shdr.request, opcode);bf_set (lpfc_mbox_hdr_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; }
@@ -1902,6 +1902,7 @@ lpfc_request_features(struct lpfc_hba *p/* 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_perfh, &mboxq->u.mqe.un.req_ftrs,1 );/* Enable DIF (block guard) only if configured to do so. */ if (phba->cfg_enable_bg)
@@ -2159,17 +2160,16 @@ lpfc_supported_pages(struct lpfcMboxq *m }/** -* lpfc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params -* mailbox command. +* lpfc_pc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params mbox cmd. * @mbox: pointer to lpfc mbox command to initialize. * * The PORT_CAPABILITIES SLI4 parameters mailbox command is issued to * retrieve the particular SLI4 features supported by the port. **/ 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)); sli4_params = &mbox->u.mqe.un.sli4_params;
drivers/scsi/lpfc/lpfc_scsi.c +14 -1
@@ -1981,12 +1981,14 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hbstruct scatterlist *sgel =NULL ;struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;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;dma_addr_t physaddr;uint32_t num_bde =0 ;uint32_t dma_len;uint32_t dma_offset =0 ;int nseg; +struct ulp_bde64 *bde;/* * There are three possibilities here - use scatter-gather segment, use
@@ -2011,7 +2013,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hbbf_set (lpfc_sli4_sge_last, sgl,0 ); sgl->word2 =cpu_to_le32 (sgl->word2); sgl +=1 ; - + first_data_sgl = sgl; lpfc_cmd->seg_cnt = nseg;if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:"
@@ -2047,6 +2049,17 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hb dma_offset += dma_len; 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 { sgl +=1 ;/* clear the last flag in the fcp_rsp map entry */
drivers/scsi/lpfc/lpfc_sli4.h +4 -0
@@ -359,6 +359,10 @@ struct lpfc_pc_sli4_params {uint32_t hdr_pp_align;uint32_t sgl_pages_max;uint32_t sgl_pp_align; +uint8_t cqv; +uint8_t mqv; +uint8_t wqv; +uint8_t rqv; };/* SLI4 HBA data structure entries */
drivers/scsi/lpfc/lpfc_sli.c +14 -7
@@ -96,7 +96,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, u/* set consumption flag every once in a while */ if (!((q->host_index +1 ) %LPFC_RELEASE_NOTIFICATION_INTERVAL ))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);/* Update the host index before invoking device */
@@ -969,7 +970,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_ }else { sglq->state =SGL_FREED ; 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 */ if (pring->txq_cnt)
@@ -4817,7 +4819,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phb "0378 No support for fcpi mode.\n"); 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 * then turn off the global config parameters to disable the
@@ -5004,7 +5009,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phbspin_lock_irq (&phba->hbalock); phba->link_state =LPFC_LINK_DOWN ;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:/* Unset all the queues set up in this routine when error out */ if (rc)
@@ -11189,7 +11195,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, sif (!mbox)return -ENOMEM ; 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_MBOX_OPCODE_FCOE_RQ_DESTROY , length,LPFC_SLI4_MBX_EMBED );
@@ -11279,7 +11285,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phbalpfc_sli4_config (phba, mbox,LPFC_MBOX_SUBSYSTEM_FCOE ,LPFC_MBOX_OPCODE_FCOE_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 *) &mbox->u.mqe.un.post_sgl_pages;
@@ -12402,7 +12408,8 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *lpfc_sli4_config (phba, mboxq,LPFC_MBOX_SUBSYSTEM_FCOE ,LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE ,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, hdr_tmpl, rpi_page->page_count); bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl,
drivers/scsi/lpfc/lpfc_vport.c +4 -0
@@ -464,6 +464,7 @@ disable_vport(struct fc_vport *fc_vport)struct lpfc_hba *phba = vport->phba;struct lpfc_nodelist *ndlp =NULL , *next_ndlp =NULL ;long timeout; +struct Scsi_Host *shost =lpfc_shost_from_vport (vport); ndlp =lpfc_findnode_did (vport, Fabric_DID); if (ndlp && NLP_CHK_NODE_ACT(ndlp)
@@ -498,6 +499,9 @@ disable_vport(struct fc_vport *fc_vport)* scsi_host_put() to release the 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_printf_vlog(vport, KERN_ERR, LOG_VPORT,