lpfc 8.3.13: Add TX Queue Support for SLI4 ELS commands.
Subsystems (2)
PATCH 5/6 lpfc 8.3.13: Add TX Queue Support for SLI4 ELS commands.
Add TX Queue Support for SLI4 ELS commands.
Signed-off-by Alex Iannicelli <[email protected]>
Signed-off-by James Smart <[email protected]>
---
lpfc.h | 5 + lpfc_attr.c | 58 ++++++++++++++++ lpfc_bsg.c | 9 ++ lpfc_crtn.h | 9 ++ lpfc_els.c | 36 +++++++--- lpfc_hbadisc.c | 2 lpfc_init.c | 8 +- lpfc_nportdisc.c | 24 +++++- lpfc_scsi.c | 4 - lpfc_sli.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++------- lpfc_sli.h | 2 11 files changed, 310 insertions(+), 41 deletions(-)
drivers/scsi/lpfc/lpfc_attr.c +58 -0
@@ -1949,6 +1949,59 @@ static DEVICE_ATTR(lpfc_enable_npiv, S_ILPFC_ATTR_R (suppress_link_up,LPFC_INITIALIZE_LINK ,LPFC_INITIALIZE_LINK ,LPFC_DELAY_INIT_LINK_INDEFINITELY ,"Suppress Link Up at initialization" ); +/* +# lpfc_cnt: Number of IOCBs allocated for ELS, CT, and ABTS +# 1 - (1024) +# 2 - (2048) +# 3 - (3072) +# 4 - (4096) +# 5 - (5120) +*/ +static ssize_t +lpfc_iocb_hw_show (struct device *dev,struct device_attribute *attr,char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; + +return snprintf (buf,PAGE_SIZE ,"%d\n" , phba->iocb_max); +} + +static DEVICE_ATTR(iocb_hw, S_IRUGO, + lpfc_iocb_hw_show, NULL); +static ssize_t +lpfc_txq_hw_show (struct device *dev,struct device_attribute *attr,char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; + +return snprintf (buf,PAGE_SIZE ,"%d\n" , + phba->sli.ring[LPFC_ELS_RING ].txq_max); +} + +static DEVICE_ATTR(txq_hw, S_IRUGO, + lpfc_txq_hw_show, NULL); +static ssize_t +lpfc_txcmplq_hw_show (struct device *dev,struct device_attribute *attr, +char *buf) +{ +struct Scsi_Host *shost =class_to_shost (dev); +struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; + +return snprintf (buf,PAGE_SIZE ,"%d\n" , + phba->sli.ring[LPFC_ELS_RING ].txcmplq_max); +} + +static DEVICE_ATTR(txcmplq_hw, S_IRUGO, + lpfc_txcmplq_hw_show, NULL); + +int lpfc_iocb_cnt =2 ; +module_param (lpfc_iocb_cnt, int,1 ); +MODULE_PARM_DESC (lpfc_iocb_cnt, +"Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs" ); +lpfc_param_show (iocb_cnt); +lpfc_param_init (iocb_cnt,2 ,1 ,5 ); +static DEVICE_ATTR(lpfc_iocb_cnt, S_IRUGO, + lpfc_iocb_cnt_show, NULL);/* # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
@@ -3334,6 +3387,10 @@ struct device_attribute *lpfc_hba_attrs[ &dev_attr_lpfc_aer_support, &dev_attr_lpfc_aer_state_cleanup, &dev_attr_lpfc_suppress_link_up, + &dev_attr_lpfc_iocb_cnt, + &dev_attr_iocb_hw, + &dev_attr_txq_hw, + &dev_attr_txcmplq_hw, NULL, };
@@ -4521,6 +4578,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)lpfc_hba_log_verbose_init (phba, lpfc_log_verbose);lpfc_aer_support_init (phba, lpfc_aer_support);lpfc_suppress_link_up_init (phba, lpfc_suppress_link_up); +lpfc_iocb_cnt_init (phba, lpfc_iocb_cnt);return ; }
drivers/scsi/lpfc/lpfc_bsg.c +9 -0
@@ -377,6 +377,11 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_jobif (rc ==IOCB_SUCCESS )return 0 ;/* done for now */ +else if (rc ==IOCB_BUSY ) + rc =EAGAIN ; +else + rc =EIO ; +/* iocb failed so cleanup */ pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
@@ -625,6 +630,10 @@ lpfc_bsg_rport_els(struct fc_bsg_job *jolpfc_nlp_put (ndlp);if (rc ==IOCB_SUCCESS )return 0 ;/* done for now */ +else if (rc ==IOCB_BUSY ) + rc =EAGAIN ; +else + rc =EIO ;pci_unmap_sg (phba->pcidev, job->request_payload.sg_list, job->request_payload.sg_cnt,DMA_TO_DEVICE );
drivers/scsi/lpfc/lpfc_crtn.h +9 -0
@@ -403,3 +403,12 @@ int lpfc_bsg_request(struct fc_bsg_job *int lpfc_bsg_timeout (struct fc_bsg_job *);int lpfc_bsg_ct_unsol_event (struct lpfc_hba *,struct lpfc_sli_ring *,struct lpfc_iocbq *); +void __lpfc_sli_ringtx_put (struct lpfc_hba *,struct lpfc_sli_ring *, +struct lpfc_iocbq *); +struct lpfc_iocbq *lpfc_sli_ringtx_get (struct lpfc_hba *, +struct lpfc_sli_ring *); +int __lpfc_sli_issue_iocb (struct lpfc_hba *,uint32_t , +struct lpfc_iocbq *,uint32_t ); +uint32_t lpfc_drain_txq (struct lpfc_hba *); + +
drivers/scsi/lpfc/lpfc_els.c +28 -8
@@ -1472,8 +1472,12 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phb } goto out; } -/* PLOGI failed */ -lpfc_printf_vlog (vport,KERN_ERR ,LOG_ELS , +/* PLOGI failed Don't print the vport to vport rjts */ +if (irsp->ulpStatus !=IOSTAT_LS_RJT || + (((irsp->un.ulpWord[4 ]) >>16 !=LSRJT_INVALID_CMD ) && + ((irsp->un.ulpWord[4 ]) >>16 !=LSRJT_UNABLE_TPC )) || + (phba)->pport->cfg_log_verbose &LOG_ELS ) +lpfc_printf_vlog (vport,KERN_ERR ,LOG_ELS ,"2753 PLOGI failure DID:%06X Status:x%x/x%x\n" , ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4 ]);
@@ -5144,6 +5148,7 @@ lpfc_els_timeout(unsigned long ptr)return ; } +/** * lpfc_els_timeout_handler - Process an els timeout event * @vport: pointer to a virtual N_Port data structure.
@@ -5164,13 +5169,19 @@ lpfc_els_timeout_handler(struct lpfc_vpouint32_t els_command =0 ;uint32_t timeout;uint32_t remote_ID =0xffffffff ; +LIST_HEAD (txcmplq_completions); +LIST_HEAD (abort_list); + -spin_lock_irq (&phba->hbalock); timeout = (uint32_t )(phba->fc_ratov <<1 ); pring = &phba->sli.ring[LPFC_ELS_RING ]; -list_for_each_entry_safe (piocb, tmp_iocb, &pring->txcmplq, list) { +spin_lock_irq (&phba->hbalock); +list_splice_init (&pring->txcmplq, &txcmplq_completions); +spin_unlock_irq (&phba->hbalock); + +list_for_each_entry_safe (piocb, tmp_iocb, &txcmplq_completions, list) { cmd = &piocb->iocb; if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 ||
@@ -5207,13 +5218,22 @@ lpfc_els_timeout_handler(struct lpfc_vpoif (ndlp &&NLP_CHK_NODE_ACT (ndlp)) remote_ID = ndlp->nlp_DID; } +list_add_tail (&piocb->dlist, &abort_list); + } +spin_lock_irq (&phba->hbalock); +list_splice (&txcmplq_completions, &pring->txcmplq); +spin_unlock_irq (&phba->hbalock); + +list_for_each_entry_safe (piocb, tmp_iocb, &abort_list, dlist) {lpfc_printf_vlog (vport,KERN_ERR ,LOG_ELS , -"0127 ELS timeout Data: x%x x%x x%x " -"x%x\n" , els_command, - remote_ID, cmd->ulpCommand, cmd->ulpIoTag); +"0127 ELS timeout Data: x%x x%x x%x " +"x%x\n" , els_command, + remote_ID, cmd->ulpCommand, cmd->ulpIoTag); +spin_lock_irq (&phba->hbalock); +list_del_init (&piocb->dlist);lpfc_sli_issue_abort_iotag (phba, pring, piocb); +spin_unlock_irq (&phba->hbalock); } -spin_unlock_irq (&phba->hbalock);if (phba->sli.ring[LPFC_ELS_RING ].txcmplq_cnt)mod_timer (&vport->els_tmofunc, jiffies +HZ * timeout);
drivers/scsi/lpfc/lpfc.h +4 -1
@@ -20,7 +20,6 @@*******************************************************************/ #include <scsi/scsi_host.h> -struct lpfc_sli2_slim ;#define LPFC_PCI_DEV_LP 0x1
@@ -376,6 +375,7 @@ struct lpfc_vport {#define WORKER_FABRIC_BLOCK_TMO 0x400/* hba: fabric block timeout */ #define WORKER_RAMP_DOWN_QUEUE 0x800/* hba: Decrease Q depth */ #define WORKER_RAMP_UP_QUEUE 0x1000/* hba: Increase Q depth */ +#define WORKER_SERVICE_TXQ 0x2000/* hba: IOCBs on the txq */ struct timer_list fc_fdmitmo;struct timer_list els_tmofunc;
@@ -624,6 +624,7 @@ struct lpfc_hba {uint32_t cfg_hostmem_hgp;uint32_t cfg_log_verbose;uint32_t cfg_aer_support; +uint32_t cfg_iocb_cnt;uint32_t cfg_suppress_link_up;#define LPFC_INITIALIZE_LINK 0/* do normal init_link mbox */ #define LPFC_DELAY_INIT_LINK 1/* layered driver hold off */
@@ -812,6 +813,8 @@ struct lpfc_hba {uint8_t menlo_flag;/* menlo generic flags */ #define HBA_MENLO_SUPPORT 0x1/* HBA supports menlo commands */ +uint32_t iocb_cnt; +uint32_t iocb_max; }; static inline struct Scsi_Host *
drivers/scsi/lpfc/lpfc_hbadisc.c +2 -0
@@ -587,6 +587,8 @@ lpfc_work_done(struct lpfc_hba *phba) (status & HA_RXMASK)); } +if (phba->pport->work_port_events &WORKER_SERVICE_TXQ ) +lpfc_drain_txq (phba);/* * Turn on Ring interrupts */
drivers/scsi/lpfc/lpfc_init.c +6 -2
@@ -8147,8 +8147,12 @@ lpfc_pci_probe_one_s4(struct pci_dev *pd }/* Initialize and populate the iocb list per host */ - error =lpfc_init_iocb_list (phba, - phba->sli4_hba.max_cfg_param.max_xri); + +lpfc_printf_log (phba,KERN_INFO ,LOG_INIT , +"2821 initialize iocb list %d.\n" , + phba->cfg_iocb_cnt*1024 ); + error =lpfc_init_iocb_list (phba, phba->cfg_iocb_cnt*1024 ); +if (error) {lpfc_printf_log (phba,KERN_ERR ,LOG_INIT ,"1413 Failed to initialize iocb list.\n" );
drivers/scsi/lpfc/lpfc_nportdisc.c +19 -5
@@ -190,6 +190,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba } +/* * Free resources / clean up outstanding I/Os * associated with a LPFC_NODELIST entry. This
@@ -199,13 +200,15 @@ int lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) {LIST_HEAD (completions); +LIST_HEAD (txcmplq_completions); +LIST_HEAD (abort_list);struct lpfc_sli *psli = &phba->sli;struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING ];struct lpfc_iocbq *iocb, *next_iocb;/* Abort outstanding I/O on NPort <nlp_DID> */ lpfc_printf_vlog (ndlp->vport,KERN_INFO ,LOG_DISCOVERY , -"0205 Abort outstanding I/O on NPort x%x " +"2819 Abort outstanding I/O on NPort x%x " "Data: x%x x%x x%x\n" , ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
@@ -224,14 +227,25 @@ lpfc_els_abort(struct lpfc_hba *phba, st }/* Next check the txcmplq */ -list_for_each_entry_safe (iocb, next_iocb, &pring->txcmplq, list) { +list_splice_init (&pring->txcmplq, &txcmplq_completions); +spin_unlock_irq (&phba->hbalock); + +list_for_each_entry_safe (iocb, next_iocb, &txcmplq_completions, list) {/* Check to see if iocb matches the nport we are looking for */ -if (lpfc_check_sli_ndlp (phba, pring, iocb, ndlp)) { -lpfc_sli_issue_abort_iotag (phba, pring, iocb); - } +if (lpfc_check_sli_ndlp (phba, pring, iocb, ndlp)) +list_add_tail (&iocb->dlist, &abort_list); } +spin_lock_irq (&phba->hbalock); +list_splice (&txcmplq_completions, &pring->txcmplq);spin_unlock_irq (&phba->hbalock); +list_for_each_entry_safe (iocb, next_iocb, &abort_list, dlist) { +spin_lock_irq (&phba->hbalock); +list_del_init (&iocb->dlist); +lpfc_sli_issue_abort_iotag (phba, pring, iocb); +spin_unlock_irq (&phba->hbalock); + } +/* Cancel all the IOCBs from the completions list */ lpfc_sli_cancel_iocbs (phba, &completions,IOSTAT_LOCAL_REJECT ,IOERR_SLI_ABORTED );
drivers/scsi/lpfc/lpfc_scsi.c +3 -1
@@ -3228,7 +3228,9 @@ lpfc_send_taskmgmt(struct lpfc_vport *vplpfc_taskmgmt_name (task_mgmt_cmd), tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, iocbqrsp->iocb.un.ulpWord[4]); - }else + }else if (status ==IOCB_BUSY ) + ret =FAILED ; +else ret =SUCCESS ;lpfc_sli_release_iocbq (phba, iocbqrsp);
drivers/scsi/lpfc/lpfc_sli.c +170 -24
337 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_sli.h +2 -0
@@ -48,6 +48,7 @@ struct lpfc_iocbq {/* lpfc_iocbqs are used in double linked lists */ struct list_head list;struct list_head clist; +struct list_head dlist;uint16_t iotag;/* pre-assigned IO tag */ uint16_t sli4_xritag;/* pre-assigned XRI, (OXID) tag. */ struct lpfc_cq_event cq_event;
@@ -64,6 +65,7 @@ struct lpfc_iocbq {#define LPFC_EXCHANGE_BUSY 0x40/* SLI4 hba reported XB in response */ #define LPFC_USE_FCPWQIDX 0x80/* Submit to specified FCPWQ index */ #define DSS_SECURITY_OP 0x100/* security IO */ +#define LPFC_IO_ON_Q 0x200/* The IO is still on the TXCMPLQ */ #define LPFC_FIP_ELS_ID_MASK 0xc000/* ELS_ID range 0-3, non-shifted mask */ #define LPFC_FIP_ELS_ID_SHIFT 14