diff options
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 58 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 36 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 24 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 194 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 2 |
11 files changed, 310 insertions, 41 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 4cb78483bf79..fcfc495d1e0d 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -20,7 +20,6 @@ | |||
20 | *******************************************************************/ | 20 | *******************************************************************/ |
21 | 21 | ||
22 | #include <scsi/scsi_host.h> | 22 | #include <scsi/scsi_host.h> |
23 | |||
24 | struct lpfc_sli2_slim; | 23 | struct lpfc_sli2_slim; |
25 | 24 | ||
26 | #define LPFC_PCI_DEV_LP 0x1 | 25 | #define LPFC_PCI_DEV_LP 0x1 |
@@ -376,6 +375,7 @@ struct lpfc_vport { | |||
376 | #define WORKER_FABRIC_BLOCK_TMO 0x400 /* hba: fabric block timeout */ | 375 | #define WORKER_FABRIC_BLOCK_TMO 0x400 /* hba: fabric block timeout */ |
377 | #define WORKER_RAMP_DOWN_QUEUE 0x800 /* hba: Decrease Q depth */ | 376 | #define WORKER_RAMP_DOWN_QUEUE 0x800 /* hba: Decrease Q depth */ |
378 | #define WORKER_RAMP_UP_QUEUE 0x1000 /* hba: Increase Q depth */ | 377 | #define WORKER_RAMP_UP_QUEUE 0x1000 /* hba: Increase Q depth */ |
378 | #define WORKER_SERVICE_TXQ 0x2000 /* hba: IOCBs on the txq */ | ||
379 | 379 | ||
380 | struct timer_list fc_fdmitmo; | 380 | struct timer_list fc_fdmitmo; |
381 | struct timer_list els_tmofunc; | 381 | struct timer_list els_tmofunc; |
@@ -624,6 +624,7 @@ struct lpfc_hba { | |||
624 | uint32_t cfg_hostmem_hgp; | 624 | uint32_t cfg_hostmem_hgp; |
625 | uint32_t cfg_log_verbose; | 625 | uint32_t cfg_log_verbose; |
626 | uint32_t cfg_aer_support; | 626 | uint32_t cfg_aer_support; |
627 | uint32_t cfg_iocb_cnt; | ||
627 | uint32_t cfg_suppress_link_up; | 628 | uint32_t cfg_suppress_link_up; |
628 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ | 629 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ |
629 | #define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */ | 630 | #define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */ |
@@ -812,6 +813,8 @@ struct lpfc_hba { | |||
812 | 813 | ||
813 | uint8_t menlo_flag; /* menlo generic flags */ | 814 | uint8_t menlo_flag; /* menlo generic flags */ |
814 | #define HBA_MENLO_SUPPORT 0x1 /* HBA supports menlo commands */ | 815 | #define HBA_MENLO_SUPPORT 0x1 /* HBA supports menlo commands */ |
816 | uint32_t iocb_cnt; | ||
817 | uint32_t iocb_max; | ||
815 | }; | 818 | }; |
816 | 819 | ||
817 | static inline struct Scsi_Host * | 820 | static inline struct Scsi_Host * |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index b17fe5149e38..39b0760c438d 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -1949,6 +1949,59 @@ static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL); | |||
1949 | LPFC_ATTR_R(suppress_link_up, LPFC_INITIALIZE_LINK, LPFC_INITIALIZE_LINK, | 1949 | LPFC_ATTR_R(suppress_link_up, LPFC_INITIALIZE_LINK, LPFC_INITIALIZE_LINK, |
1950 | LPFC_DELAY_INIT_LINK_INDEFINITELY, | 1950 | LPFC_DELAY_INIT_LINK_INDEFINITELY, |
1951 | "Suppress Link Up at initialization"); | 1951 | "Suppress Link Up at initialization"); |
1952 | /* | ||
1953 | # lpfc_cnt: Number of IOCBs allocated for ELS, CT, and ABTS | ||
1954 | # 1 - (1024) | ||
1955 | # 2 - (2048) | ||
1956 | # 3 - (3072) | ||
1957 | # 4 - (4096) | ||
1958 | # 5 - (5120) | ||
1959 | */ | ||
1960 | static ssize_t | ||
1961 | lpfc_iocb_hw_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1962 | { | ||
1963 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1964 | struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; | ||
1965 | |||
1966 | return snprintf(buf, PAGE_SIZE, "%d\n", phba->iocb_max); | ||
1967 | } | ||
1968 | |||
1969 | static DEVICE_ATTR(iocb_hw, S_IRUGO, | ||
1970 | lpfc_iocb_hw_show, NULL); | ||
1971 | static ssize_t | ||
1972 | lpfc_txq_hw_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1973 | { | ||
1974 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1975 | struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; | ||
1976 | |||
1977 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1978 | phba->sli.ring[LPFC_ELS_RING].txq_max); | ||
1979 | } | ||
1980 | |||
1981 | static DEVICE_ATTR(txq_hw, S_IRUGO, | ||
1982 | lpfc_txq_hw_show, NULL); | ||
1983 | static ssize_t | ||
1984 | lpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr, | ||
1985 | char *buf) | ||
1986 | { | ||
1987 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1988 | struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; | ||
1989 | |||
1990 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1991 | phba->sli.ring[LPFC_ELS_RING].txcmplq_max); | ||
1992 | } | ||
1993 | |||
1994 | static DEVICE_ATTR(txcmplq_hw, S_IRUGO, | ||
1995 | lpfc_txcmplq_hw_show, NULL); | ||
1996 | |||
1997 | int lpfc_iocb_cnt = 2; | ||
1998 | module_param(lpfc_iocb_cnt, int, 1); | ||
1999 | MODULE_PARM_DESC(lpfc_iocb_cnt, | ||
2000 | "Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs"); | ||
2001 | lpfc_param_show(iocb_cnt); | ||
2002 | lpfc_param_init(iocb_cnt, 2, 1, 5); | ||
2003 | static DEVICE_ATTR(lpfc_iocb_cnt, S_IRUGO, | ||
2004 | lpfc_iocb_cnt_show, NULL); | ||
1952 | 2005 | ||
1953 | /* | 2006 | /* |
1954 | # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear | 2007 | # 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[] = { | |||
3334 | &dev_attr_lpfc_aer_support, | 3387 | &dev_attr_lpfc_aer_support, |
3335 | &dev_attr_lpfc_aer_state_cleanup, | 3388 | &dev_attr_lpfc_aer_state_cleanup, |
3336 | &dev_attr_lpfc_suppress_link_up, | 3389 | &dev_attr_lpfc_suppress_link_up, |
3390 | &dev_attr_lpfc_iocb_cnt, | ||
3391 | &dev_attr_iocb_hw, | ||
3392 | &dev_attr_txq_hw, | ||
3393 | &dev_attr_txcmplq_hw, | ||
3337 | NULL, | 3394 | NULL, |
3338 | }; | 3395 | }; |
3339 | 3396 | ||
@@ -4521,6 +4578,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
4521 | lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); | 4578 | lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); |
4522 | lpfc_aer_support_init(phba, lpfc_aer_support); | 4579 | lpfc_aer_support_init(phba, lpfc_aer_support); |
4523 | lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); | 4580 | lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); |
4581 | lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); | ||
4524 | return; | 4582 | return; |
4525 | } | 4583 | } |
4526 | 4584 | ||
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index dcf088262b20..55f984166dbc 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -377,6 +377,11 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) | |||
377 | 377 | ||
378 | if (rc == IOCB_SUCCESS) | 378 | if (rc == IOCB_SUCCESS) |
379 | return 0; /* done for now */ | 379 | return 0; /* done for now */ |
380 | else if (rc == IOCB_BUSY) | ||
381 | rc = EAGAIN; | ||
382 | else | ||
383 | rc = EIO; | ||
384 | |||
380 | 385 | ||
381 | /* iocb failed so cleanup */ | 386 | /* iocb failed so cleanup */ |
382 | pci_unmap_sg(phba->pcidev, job->request_payload.sg_list, | 387 | pci_unmap_sg(phba->pcidev, job->request_payload.sg_list, |
@@ -625,6 +630,10 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job) | |||
625 | lpfc_nlp_put(ndlp); | 630 | lpfc_nlp_put(ndlp); |
626 | if (rc == IOCB_SUCCESS) | 631 | if (rc == IOCB_SUCCESS) |
627 | return 0; /* done for now */ | 632 | return 0; /* done for now */ |
633 | else if (rc == IOCB_BUSY) | ||
634 | rc = EAGAIN; | ||
635 | else | ||
636 | rc = EIO; | ||
628 | 637 | ||
629 | pci_unmap_sg(phba->pcidev, job->request_payload.sg_list, | 638 | pci_unmap_sg(phba->pcidev, job->request_payload.sg_list, |
630 | job->request_payload.sg_cnt, DMA_TO_DEVICE); | 639 | job->request_payload.sg_cnt, DMA_TO_DEVICE); |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 6b404e510a3b..361f4e7e23e4 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -403,3 +403,12 @@ int lpfc_bsg_request(struct fc_bsg_job *); | |||
403 | int lpfc_bsg_timeout(struct fc_bsg_job *); | 403 | int lpfc_bsg_timeout(struct fc_bsg_job *); |
404 | int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, | 404 | int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, |
405 | struct lpfc_iocbq *); | 405 | struct lpfc_iocbq *); |
406 | void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *, | ||
407 | struct lpfc_iocbq *); | ||
408 | struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *, | ||
409 | struct lpfc_sli_ring *); | ||
410 | int __lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, | ||
411 | struct lpfc_iocbq *, uint32_t); | ||
412 | uint32_t lpfc_drain_txq(struct lpfc_hba *); | ||
413 | |||
414 | |||
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6b1850c9fdff..f936f8c7efe1 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -1472,8 +1472,12 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1472 | } | 1472 | } |
1473 | goto out; | 1473 | goto out; |
1474 | } | 1474 | } |
1475 | /* PLOGI failed */ | 1475 | /* PLOGI failed Don't print the vport to vport rjts */ |
1476 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 1476 | if (irsp->ulpStatus != IOSTAT_LS_RJT || |
1477 | (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && | ||
1478 | ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || | ||
1479 | (phba)->pport->cfg_log_verbose & LOG_ELS) | ||
1480 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
1477 | "2753 PLOGI failure DID:%06X Status:x%x/x%x\n", | 1481 | "2753 PLOGI failure DID:%06X Status:x%x/x%x\n", |
1478 | ndlp->nlp_DID, irsp->ulpStatus, | 1482 | ndlp->nlp_DID, irsp->ulpStatus, |
1479 | irsp->un.ulpWord[4]); | 1483 | irsp->un.ulpWord[4]); |
@@ -5144,6 +5148,7 @@ lpfc_els_timeout(unsigned long ptr) | |||
5144 | return; | 5148 | return; |
5145 | } | 5149 | } |
5146 | 5150 | ||
5151 | |||
5147 | /** | 5152 | /** |
5148 | * lpfc_els_timeout_handler - Process an els timeout event | 5153 | * lpfc_els_timeout_handler - Process an els timeout event |
5149 | * @vport: pointer to a virtual N_Port data structure. | 5154 | * @vport: pointer to a virtual N_Port data structure. |
@@ -5164,13 +5169,19 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) | |||
5164 | uint32_t els_command = 0; | 5169 | uint32_t els_command = 0; |
5165 | uint32_t timeout; | 5170 | uint32_t timeout; |
5166 | uint32_t remote_ID = 0xffffffff; | 5171 | uint32_t remote_ID = 0xffffffff; |
5172 | LIST_HEAD(txcmplq_completions); | ||
5173 | LIST_HEAD(abort_list); | ||
5174 | |||
5167 | 5175 | ||
5168 | spin_lock_irq(&phba->hbalock); | ||
5169 | timeout = (uint32_t)(phba->fc_ratov << 1); | 5176 | timeout = (uint32_t)(phba->fc_ratov << 1); |
5170 | 5177 | ||
5171 | pring = &phba->sli.ring[LPFC_ELS_RING]; | 5178 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
5172 | 5179 | ||
5173 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | 5180 | spin_lock_irq(&phba->hbalock); |
5181 | list_splice_init(&pring->txcmplq, &txcmplq_completions); | ||
5182 | spin_unlock_irq(&phba->hbalock); | ||
5183 | |||
5184 | list_for_each_entry_safe(piocb, tmp_iocb, &txcmplq_completions, list) { | ||
5174 | cmd = &piocb->iocb; | 5185 | cmd = &piocb->iocb; |
5175 | 5186 | ||
5176 | if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || | 5187 | if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || |
@@ -5207,13 +5218,22 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) | |||
5207 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) | 5218 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) |
5208 | remote_ID = ndlp->nlp_DID; | 5219 | remote_ID = ndlp->nlp_DID; |
5209 | } | 5220 | } |
5221 | list_add_tail(&piocb->dlist, &abort_list); | ||
5222 | } | ||
5223 | spin_lock_irq(&phba->hbalock); | ||
5224 | list_splice(&txcmplq_completions, &pring->txcmplq); | ||
5225 | spin_unlock_irq(&phba->hbalock); | ||
5226 | |||
5227 | list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { | ||
5210 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 5228 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
5211 | "0127 ELS timeout Data: x%x x%x x%x " | 5229 | "0127 ELS timeout Data: x%x x%x x%x " |
5212 | "x%x\n", els_command, | 5230 | "x%x\n", els_command, |
5213 | remote_ID, cmd->ulpCommand, cmd->ulpIoTag); | 5231 | remote_ID, cmd->ulpCommand, cmd->ulpIoTag); |
5232 | spin_lock_irq(&phba->hbalock); | ||
5233 | list_del_init(&piocb->dlist); | ||
5214 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); | 5234 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); |
5235 | spin_unlock_irq(&phba->hbalock); | ||
5215 | } | 5236 | } |
5216 | spin_unlock_irq(&phba->hbalock); | ||
5217 | 5237 | ||
5218 | if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) | 5238 | if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) |
5219 | mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); | 5239 | mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 8082d69ea730..d1c5c52b1c25 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -587,6 +587,8 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
587 | (status & | 587 | (status & |
588 | HA_RXMASK)); | 588 | HA_RXMASK)); |
589 | } | 589 | } |
590 | if (phba->pport->work_port_events & WORKER_SERVICE_TXQ) | ||
591 | lpfc_drain_txq(phba); | ||
590 | /* | 592 | /* |
591 | * Turn on Ring interrupts | 593 | * Turn on Ring interrupts |
592 | */ | 594 | */ |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7dc55989b8ff..184e45f286d2 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -8147,8 +8147,12 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
8147 | } | 8147 | } |
8148 | 8148 | ||
8149 | /* Initialize and populate the iocb list per host */ | 8149 | /* Initialize and populate the iocb list per host */ |
8150 | error = lpfc_init_iocb_list(phba, | 8150 | |
8151 | phba->sli4_hba.max_cfg_param.max_xri); | 8151 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
8152 | "2821 initialize iocb list %d.\n", | ||
8153 | phba->cfg_iocb_cnt*1024); | ||
8154 | error = lpfc_init_iocb_list(phba, phba->cfg_iocb_cnt*1024); | ||
8155 | |||
8152 | if (error) { | 8156 | if (error) { |
8153 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 8157 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
8154 | "1413 Failed to initialize iocb list.\n"); | 8158 | "1413 Failed to initialize iocb list.\n"); |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 9810b3d3cc53..bccc9c66fa37 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -190,6 +190,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
190 | } | 190 | } |
191 | 191 | ||
192 | 192 | ||
193 | |||
193 | /* | 194 | /* |
194 | * Free resources / clean up outstanding I/Os | 195 | * Free resources / clean up outstanding I/Os |
195 | * associated with a LPFC_NODELIST entry. This | 196 | * associated with a LPFC_NODELIST entry. This |
@@ -199,13 +200,15 @@ int | |||
199 | lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | 200 | lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) |
200 | { | 201 | { |
201 | LIST_HEAD(completions); | 202 | LIST_HEAD(completions); |
203 | LIST_HEAD(txcmplq_completions); | ||
204 | LIST_HEAD(abort_list); | ||
202 | struct lpfc_sli *psli = &phba->sli; | 205 | struct lpfc_sli *psli = &phba->sli; |
203 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; | 206 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; |
204 | struct lpfc_iocbq *iocb, *next_iocb; | 207 | struct lpfc_iocbq *iocb, *next_iocb; |
205 | 208 | ||
206 | /* Abort outstanding I/O on NPort <nlp_DID> */ | 209 | /* Abort outstanding I/O on NPort <nlp_DID> */ |
207 | lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY, | 210 | lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY, |
208 | "0205 Abort outstanding I/O on NPort x%x " | 211 | "2819 Abort outstanding I/O on NPort x%x " |
209 | "Data: x%x x%x x%x\n", | 212 | "Data: x%x x%x x%x\n", |
210 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, | 213 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, |
211 | ndlp->nlp_rpi); | 214 | ndlp->nlp_rpi); |
@@ -224,14 +227,25 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
224 | } | 227 | } |
225 | 228 | ||
226 | /* Next check the txcmplq */ | 229 | /* Next check the txcmplq */ |
227 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 230 | list_splice_init(&pring->txcmplq, &txcmplq_completions); |
231 | spin_unlock_irq(&phba->hbalock); | ||
232 | |||
233 | list_for_each_entry_safe(iocb, next_iocb, &txcmplq_completions, list) { | ||
228 | /* Check to see if iocb matches the nport we are looking for */ | 234 | /* Check to see if iocb matches the nport we are looking for */ |
229 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { | 235 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) |
230 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); | 236 | list_add_tail(&iocb->dlist, &abort_list); |
231 | } | ||
232 | } | 237 | } |
238 | spin_lock_irq(&phba->hbalock); | ||
239 | list_splice(&txcmplq_completions, &pring->txcmplq); | ||
233 | spin_unlock_irq(&phba->hbalock); | 240 | spin_unlock_irq(&phba->hbalock); |
234 | 241 | ||
242 | list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) { | ||
243 | spin_lock_irq(&phba->hbalock); | ||
244 | list_del_init(&iocb->dlist); | ||
245 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); | ||
246 | spin_unlock_irq(&phba->hbalock); | ||
247 | } | ||
248 | |||
235 | /* Cancel all the IOCBs from the completions list */ | 249 | /* Cancel all the IOCBs from the completions list */ |
236 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, | 250 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, |
237 | IOERR_SLI_ABORTED); | 251 | IOERR_SLI_ABORTED); |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f7a92653467a..c6bdf63925d9 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -3228,7 +3228,9 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, | |||
3228 | lpfc_taskmgmt_name(task_mgmt_cmd), | 3228 | lpfc_taskmgmt_name(task_mgmt_cmd), |
3229 | tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, | 3229 | tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, |
3230 | iocbqrsp->iocb.un.ulpWord[4]); | 3230 | iocbqrsp->iocb.un.ulpWord[4]); |
3231 | } else | 3231 | } else if (status == IOCB_BUSY) |
3232 | ret = FAILED; | ||
3233 | else | ||
3232 | ret = SUCCESS; | 3234 | ret = SUCCESS; |
3233 | 3235 | ||
3234 | lpfc_sli_release_iocbq(phba, iocbqrsp); | 3236 | lpfc_sli_release_iocbq(phba, iocbqrsp); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 103a5aa4ae81..ae3cb0ab0ae4 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -455,6 +455,11 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba) | |||
455 | struct lpfc_iocbq * iocbq = NULL; | 455 | struct lpfc_iocbq * iocbq = NULL; |
456 | 456 | ||
457 | list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list); | 457 | list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list); |
458 | |||
459 | if (iocbq) | ||
460 | phba->iocb_cnt++; | ||
461 | if (phba->iocb_cnt > phba->iocb_max) | ||
462 | phba->iocb_max = phba->iocb_cnt; | ||
458 | return iocbq; | 463 | return iocbq; |
459 | } | 464 | } |
460 | 465 | ||
@@ -575,7 +580,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
575 | { | 580 | { |
576 | struct lpfc_sglq *sglq; | 581 | struct lpfc_sglq *sglq; |
577 | size_t start_clean = offsetof(struct lpfc_iocbq, iocb); | 582 | size_t start_clean = offsetof(struct lpfc_iocbq, iocb); |
578 | unsigned long iflag; | 583 | unsigned long iflag = 0; |
584 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | ||
579 | 585 | ||
580 | if (iocbq->sli4_xritag == NO_XRI) | 586 | if (iocbq->sli4_xritag == NO_XRI) |
581 | sglq = NULL; | 587 | sglq = NULL; |
@@ -593,6 +599,17 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
593 | } else { | 599 | } else { |
594 | sglq->state = SGL_FREED; | 600 | sglq->state = SGL_FREED; |
595 | list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); | 601 | list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); |
602 | |||
603 | /* Check if TXQ queue needs to be serviced */ | ||
604 | if (pring->txq_cnt) { | ||
605 | spin_lock_irqsave( | ||
606 | &phba->pport->work_port_lock, iflag); | ||
607 | phba->pport->work_port_events |= | ||
608 | WORKER_SERVICE_TXQ; | ||
609 | lpfc_worker_wake_up(phba); | ||
610 | spin_unlock_irqrestore( | ||
611 | &phba->pport->work_port_lock, iflag); | ||
612 | } | ||
596 | } | 613 | } |
597 | } | 614 | } |
598 | 615 | ||
@@ -605,6 +622,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
605 | list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); | 622 | list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); |
606 | } | 623 | } |
607 | 624 | ||
625 | |||
608 | /** | 626 | /** |
609 | * __lpfc_sli_release_iocbq_s3 - Release iocb to the iocb pool | 627 | * __lpfc_sli_release_iocbq_s3 - Release iocb to the iocb pool |
610 | * @phba: Pointer to HBA context object. | 628 | * @phba: Pointer to HBA context object. |
@@ -642,6 +660,7 @@ static void | |||
642 | __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | 660 | __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) |
643 | { | 661 | { |
644 | phba->__lpfc_sli_release_iocbq(phba, iocbq); | 662 | phba->__lpfc_sli_release_iocbq(phba, iocbq); |
663 | phba->iocb_cnt--; | ||
645 | } | 664 | } |
646 | 665 | ||
647 | /** | 666 | /** |
@@ -872,7 +891,11 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
872 | struct lpfc_iocbq *piocb) | 891 | struct lpfc_iocbq *piocb) |
873 | { | 892 | { |
874 | list_add_tail(&piocb->list, &pring->txcmplq); | 893 | list_add_tail(&piocb->list, &pring->txcmplq); |
894 | piocb->iocb_flag |= LPFC_IO_ON_Q; | ||
875 | pring->txcmplq_cnt++; | 895 | pring->txcmplq_cnt++; |
896 | if (pring->txcmplq_cnt > pring->txcmplq_max) | ||
897 | pring->txcmplq_max = pring->txcmplq_cnt; | ||
898 | |||
876 | if ((unlikely(pring->ringno == LPFC_ELS_RING)) && | 899 | if ((unlikely(pring->ringno == LPFC_ELS_RING)) && |
877 | (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && | 900 | (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && |
878 | (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) { | 901 | (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) { |
@@ -897,7 +920,7 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
897 | * the txq, the function returns first iocb in the list after | 920 | * the txq, the function returns first iocb in the list after |
898 | * removing the iocb from the list, else it returns NULL. | 921 | * removing the iocb from the list, else it returns NULL. |
899 | **/ | 922 | **/ |
900 | static struct lpfc_iocbq * | 923 | struct lpfc_iocbq * |
901 | lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | 924 | lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) |
902 | { | 925 | { |
903 | struct lpfc_iocbq *cmd_iocb; | 926 | struct lpfc_iocbq *cmd_iocb; |
@@ -2150,7 +2173,10 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, | |||
2150 | if (iotag != 0 && iotag <= phba->sli.last_iotag) { | 2173 | if (iotag != 0 && iotag <= phba->sli.last_iotag) { |
2151 | cmd_iocb = phba->sli.iocbq_lookup[iotag]; | 2174 | cmd_iocb = phba->sli.iocbq_lookup[iotag]; |
2152 | list_del_init(&cmd_iocb->list); | 2175 | list_del_init(&cmd_iocb->list); |
2153 | pring->txcmplq_cnt--; | 2176 | if (cmd_iocb->iocb_flag & LPFC_IO_ON_Q) { |
2177 | pring->txcmplq_cnt--; | ||
2178 | cmd_iocb->iocb_flag &= ~LPFC_IO_ON_Q; | ||
2179 | } | ||
2154 | return cmd_iocb; | 2180 | return cmd_iocb; |
2155 | } | 2181 | } |
2156 | 2182 | ||
@@ -2183,7 +2209,10 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba, | |||
2183 | if (iotag != 0 && iotag <= phba->sli.last_iotag) { | 2209 | if (iotag != 0 && iotag <= phba->sli.last_iotag) { |
2184 | cmd_iocb = phba->sli.iocbq_lookup[iotag]; | 2210 | cmd_iocb = phba->sli.iocbq_lookup[iotag]; |
2185 | list_del_init(&cmd_iocb->list); | 2211 | list_del_init(&cmd_iocb->list); |
2186 | pring->txcmplq_cnt--; | 2212 | if (cmd_iocb->iocb_flag & LPFC_IO_ON_Q) { |
2213 | cmd_iocb->iocb_flag &= ~LPFC_IO_ON_Q; | ||
2214 | pring->txcmplq_cnt--; | ||
2215 | } | ||
2187 | return cmd_iocb; | 2216 | return cmd_iocb; |
2188 | } | 2217 | } |
2189 | 2218 | ||
@@ -5578,7 +5607,7 @@ lpfc_mbox_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) | |||
5578 | * iocb to the txq when SLI layer cannot submit the command iocb | 5607 | * iocb to the txq when SLI layer cannot submit the command iocb |
5579 | * to the ring. | 5608 | * to the ring. |
5580 | **/ | 5609 | **/ |
5581 | static void | 5610 | void |
5582 | __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 5611 | __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
5583 | struct lpfc_iocbq *piocb) | 5612 | struct lpfc_iocbq *piocb) |
5584 | { | 5613 | { |
@@ -6195,7 +6224,6 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6195 | struct lpfc_iocbq *piocb, uint32_t flag) | 6224 | struct lpfc_iocbq *piocb, uint32_t flag) |
6196 | { | 6225 | { |
6197 | struct lpfc_sglq *sglq; | 6226 | struct lpfc_sglq *sglq; |
6198 | uint16_t xritag; | ||
6199 | union lpfc_wqe wqe; | 6227 | union lpfc_wqe wqe; |
6200 | struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number]; | 6228 | struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number]; |
6201 | 6229 | ||
@@ -6204,10 +6232,26 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6204 | piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) | 6232 | piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) |
6205 | sglq = NULL; | 6233 | sglq = NULL; |
6206 | else { | 6234 | else { |
6235 | if (pring->txq_cnt) { | ||
6236 | if (!(flag & SLI_IOCB_RET_IOCB)) { | ||
6237 | __lpfc_sli_ringtx_put(phba, | ||
6238 | pring, piocb); | ||
6239 | return IOCB_SUCCESS; | ||
6240 | } else { | ||
6241 | return IOCB_BUSY; | ||
6242 | } | ||
6243 | } else { | ||
6207 | sglq = __lpfc_sli_get_sglq(phba); | 6244 | sglq = __lpfc_sli_get_sglq(phba); |
6208 | if (!sglq) | 6245 | if (!sglq) { |
6209 | return IOCB_ERROR; | 6246 | if (!(flag & SLI_IOCB_RET_IOCB)) { |
6210 | piocb->sli4_xritag = sglq->sli4_xritag; | 6247 | __lpfc_sli_ringtx_put(phba, |
6248 | pring, | ||
6249 | piocb); | ||
6250 | return IOCB_SUCCESS; | ||
6251 | } else | ||
6252 | return IOCB_BUSY; | ||
6253 | } | ||
6254 | } | ||
6211 | } | 6255 | } |
6212 | } else if (piocb->iocb_flag & LPFC_IO_FCP) { | 6256 | } else if (piocb->iocb_flag & LPFC_IO_FCP) { |
6213 | sglq = NULL; /* These IO's already have an XRI and | 6257 | sglq = NULL; /* These IO's already have an XRI and |
@@ -6223,8 +6267,9 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6223 | } | 6267 | } |
6224 | 6268 | ||
6225 | if (sglq) { | 6269 | if (sglq) { |
6226 | xritag = lpfc_sli4_bpl2sgl(phba, piocb, sglq); | 6270 | piocb->sli4_xritag = sglq->sli4_xritag; |
6227 | if (xritag != sglq->sli4_xritag) | 6271 | |
6272 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq)) | ||
6228 | return IOCB_ERROR; | 6273 | return IOCB_ERROR; |
6229 | } | 6274 | } |
6230 | 6275 | ||
@@ -6264,7 +6309,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6264 | * IOCB_SUCCESS - Success | 6309 | * IOCB_SUCCESS - Success |
6265 | * IOCB_BUSY - Busy | 6310 | * IOCB_BUSY - Busy |
6266 | **/ | 6311 | **/ |
6267 | static inline int | 6312 | int |
6268 | __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, | 6313 | __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, |
6269 | struct lpfc_iocbq *piocb, uint32_t flag) | 6314 | struct lpfc_iocbq *piocb, uint32_t flag) |
6270 | { | 6315 | { |
@@ -7081,13 +7126,6 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
7081 | */ | 7126 | */ |
7082 | abort_iocb = phba->sli.iocbq_lookup[abort_context]; | 7127 | abort_iocb = phba->sli.iocbq_lookup[abort_context]; |
7083 | 7128 | ||
7084 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_SLI, | ||
7085 | "0327 Cannot abort els iocb %p " | ||
7086 | "with tag %x context %x, abort status %x, " | ||
7087 | "abort code %x\n", | ||
7088 | abort_iocb, abort_iotag, abort_context, | ||
7089 | irsp->ulpStatus, irsp->un.ulpWord[4]); | ||
7090 | |||
7091 | /* | 7129 | /* |
7092 | * If the iocb is not found in Firmware queue the iocb | 7130 | * If the iocb is not found in Firmware queue the iocb |
7093 | * might have completed already. Do not free it again. | 7131 | * might have completed already. Do not free it again. |
@@ -7106,6 +7144,13 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
7106 | if (abort_iocb && phba->sli_rev == LPFC_SLI_REV4) | 7144 | if (abort_iocb && phba->sli_rev == LPFC_SLI_REV4) |
7107 | abort_context = abort_iocb->iocb.ulpContext; | 7145 | abort_context = abort_iocb->iocb.ulpContext; |
7108 | } | 7146 | } |
7147 | |||
7148 | lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_SLI, | ||
7149 | "0327 Cannot abort els iocb %p " | ||
7150 | "with tag %x context %x, abort status %x, " | ||
7151 | "abort code %x\n", | ||
7152 | abort_iocb, abort_iotag, abort_context, | ||
7153 | irsp->ulpStatus, irsp->un.ulpWord[4]); | ||
7109 | /* | 7154 | /* |
7110 | * make sure we have the right iocbq before taking it | 7155 | * make sure we have the right iocbq before taking it |
7111 | * off the txcmplq and try to call completion routine. | 7156 | * off the txcmplq and try to call completion routine. |
@@ -7123,7 +7168,10 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
7123 | * following abort XRI from the HBA. | 7168 | * following abort XRI from the HBA. |
7124 | */ | 7169 | */ |
7125 | list_del_init(&abort_iocb->list); | 7170 | list_del_init(&abort_iocb->list); |
7126 | pring->txcmplq_cnt--; | 7171 | if (abort_iocb->iocb_flag & LPFC_IO_ON_Q) { |
7172 | abort_iocb->iocb_flag &= ~LPFC_IO_ON_Q; | ||
7173 | pring->txcmplq_cnt--; | ||
7174 | } | ||
7127 | 7175 | ||
7128 | /* Firmware could still be in progress of DMAing | 7176 | /* Firmware could still be in progress of DMAing |
7129 | * payload, so don't free data buffer till after | 7177 | * payload, so don't free data buffer till after |
@@ -7255,8 +7303,9 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
7255 | lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, | 7303 | lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, |
7256 | "0339 Abort xri x%x, original iotag x%x, " | 7304 | "0339 Abort xri x%x, original iotag x%x, " |
7257 | "abort cmd iotag x%x\n", | 7305 | "abort cmd iotag x%x\n", |
7306 | iabt->un.acxri.abortIoTag, | ||
7258 | iabt->un.acxri.abortContextTag, | 7307 | iabt->un.acxri.abortContextTag, |
7259 | iabt->un.acxri.abortIoTag, abtsiocbp->iotag); | 7308 | abtsiocbp->iotag); |
7260 | retval = __lpfc_sli_issue_iocb(phba, pring->ringno, abtsiocbp, 0); | 7309 | retval = __lpfc_sli_issue_iocb(phba, pring->ringno, abtsiocbp, 0); |
7261 | 7310 | ||
7262 | if (retval) | 7311 | if (retval) |
@@ -7586,7 +7635,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, | |||
7586 | long timeleft, timeout_req = 0; | 7635 | long timeleft, timeout_req = 0; |
7587 | int retval = IOCB_SUCCESS; | 7636 | int retval = IOCB_SUCCESS; |
7588 | uint32_t creg_val; | 7637 | uint32_t creg_val; |
7589 | 7638 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | |
7590 | /* | 7639 | /* |
7591 | * If the caller has provided a response iocbq buffer, then context2 | 7640 | * If the caller has provided a response iocbq buffer, then context2 |
7592 | * is NULL or its an error. | 7641 | * is NULL or its an error. |
@@ -7608,7 +7657,8 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, | |||
7608 | readl(phba->HCregaddr); /* flush */ | 7657 | readl(phba->HCregaddr); /* flush */ |
7609 | } | 7658 | } |
7610 | 7659 | ||
7611 | retval = lpfc_sli_issue_iocb(phba, ring_number, piocb, 0); | 7660 | retval = lpfc_sli_issue_iocb(phba, ring_number, piocb, |
7661 | SLI_IOCB_RET_IOCB); | ||
7612 | if (retval == IOCB_SUCCESS) { | 7662 | if (retval == IOCB_SUCCESS) { |
7613 | timeout_req = timeout * HZ; | 7663 | timeout_req = timeout * HZ; |
7614 | timeleft = wait_event_timeout(done_q, | 7664 | timeleft = wait_event_timeout(done_q, |
@@ -7630,6 +7680,11 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, | |||
7630 | timeout, (timeleft / jiffies)); | 7680 | timeout, (timeleft / jiffies)); |
7631 | retval = IOCB_TIMEDOUT; | 7681 | retval = IOCB_TIMEDOUT; |
7632 | } | 7682 | } |
7683 | } else if (retval == IOCB_BUSY) { | ||
7684 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
7685 | "2818 Max IOCBs %d txq cnt %d txcmplq cnt %d\n", | ||
7686 | phba->iocb_cnt, pring->txq_cnt, pring->txcmplq_cnt); | ||
7687 | return retval; | ||
7633 | } else { | 7688 | } else { |
7634 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 7689 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
7635 | "0332 IOCB wait issue failed, Data x%x\n", | 7690 | "0332 IOCB wait issue failed, Data x%x\n", |
@@ -8775,12 +8830,17 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, | |||
8775 | { | 8830 | { |
8776 | struct lpfc_iocbq *irspiocbq; | 8831 | struct lpfc_iocbq *irspiocbq; |
8777 | unsigned long iflags; | 8832 | unsigned long iflags; |
8833 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_FCP_RING]; | ||
8778 | 8834 | ||
8779 | /* Get an irspiocbq for later ELS response processing use */ | 8835 | /* Get an irspiocbq for later ELS response processing use */ |
8780 | irspiocbq = lpfc_sli_get_iocbq(phba); | 8836 | irspiocbq = lpfc_sli_get_iocbq(phba); |
8781 | if (!irspiocbq) { | 8837 | if (!irspiocbq) { |
8782 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 8838 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
8783 | "0387 Failed to allocate an iocbq\n"); | 8839 | "0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d " |
8840 | "fcp_txcmplq_cnt=%d, els_txcmplq_cnt=%d\n", | ||
8841 | pring->txq_cnt, phba->iocb_cnt, | ||
8842 | phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt, | ||
8843 | phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt); | ||
8784 | return false; | 8844 | return false; |
8785 | } | 8845 | } |
8786 | 8846 | ||
@@ -12695,3 +12755,89 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) | |||
12695 | spin_unlock_irq(&phba->hbalock); | 12755 | spin_unlock_irq(&phba->hbalock); |
12696 | } | 12756 | } |
12697 | 12757 | ||
12758 | /** | ||
12759 | * lpfc_drain_txq - Drain the txq | ||
12760 | * @phba: Pointer to HBA context object. | ||
12761 | * | ||
12762 | * This function attempt to submit IOCBs on the txq | ||
12763 | * to the adapter. For SLI4 adapters, the txq contains | ||
12764 | * ELS IOCBs that have been deferred because the there | ||
12765 | * are no SGLs. This congestion can occur with large | ||
12766 | * vport counts during node discovery. | ||
12767 | **/ | ||
12768 | |||
12769 | uint32_t | ||
12770 | lpfc_drain_txq(struct lpfc_hba *phba) | ||
12771 | { | ||
12772 | LIST_HEAD(completions); | ||
12773 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | ||
12774 | struct lpfc_iocbq *piocbq = 0; | ||
12775 | unsigned long iflags = 0; | ||
12776 | char *fail_msg = NULL; | ||
12777 | struct lpfc_sglq *sglq; | ||
12778 | union lpfc_wqe wqe; | ||
12779 | |||
12780 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
12781 | if (pring->txq_cnt > pring->txq_max) | ||
12782 | pring->txq_max = pring->txq_cnt; | ||
12783 | |||
12784 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
12785 | |||
12786 | while (pring->txq_cnt) { | ||
12787 | spin_lock_irqsave(&phba->hbalock, iflags); | ||
12788 | |||
12789 | sglq = __lpfc_sli_get_sglq(phba); | ||
12790 | if (!sglq) { | ||
12791 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
12792 | break; | ||
12793 | } else { | ||
12794 | piocbq = lpfc_sli_ringtx_get(phba, pring); | ||
12795 | if (!piocbq) { | ||
12796 | /* The txq_cnt out of sync. This should | ||
12797 | * never happen | ||
12798 | */ | ||
12799 | sglq = __lpfc_clear_active_sglq(phba, | ||
12800 | sglq->sli4_xritag); | ||
12801 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
12802 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
12803 | "2823 txq empty and txq_cnt is %d\n ", | ||
12804 | pring->txq_cnt); | ||
12805 | break; | ||
12806 | } | ||
12807 | } | ||
12808 | |||
12809 | /* The xri and iocb resources secured, | ||
12810 | * attempt to issue request | ||
12811 | */ | ||
12812 | piocbq->sli4_xritag = sglq->sli4_xritag; | ||
12813 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) | ||
12814 | fail_msg = "to convert bpl to sgl"; | ||
12815 | else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe)) | ||
12816 | fail_msg = "to convert iocb to wqe"; | ||
12817 | else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) | ||
12818 | fail_msg = " - Wq is full"; | ||
12819 | else | ||
12820 | lpfc_sli_ringtxcmpl_put(phba, pring, piocbq); | ||
12821 | |||
12822 | if (fail_msg) { | ||
12823 | /* Failed means we can't issue and need to cancel */ | ||
12824 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
12825 | "2822 IOCB failed %s iotag 0x%x " | ||
12826 | "xri 0x%x\n", | ||
12827 | fail_msg, | ||
12828 | piocbq->iotag, piocbq->sli4_xritag); | ||
12829 | list_add_tail(&piocbq->list, &completions); | ||
12830 | } | ||
12831 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
12832 | } | ||
12833 | |||
12834 | spin_lock_irqsave(&phba->pport->work_port_lock, iflags); | ||
12835 | phba->pport->work_port_events &= ~WORKER_SERVICE_TXQ; | ||
12836 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags); | ||
12837 | |||
12838 | /* Cancel all the IOCBs that cannot be issued */ | ||
12839 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, | ||
12840 | IOERR_SLI_ABORTED); | ||
12841 | |||
12842 | return pring->txq_cnt; | ||
12843 | } | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index e3792151ca06..cd56d6cce6c3 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -48,6 +48,7 @@ struct lpfc_iocbq { | |||
48 | /* lpfc_iocbqs are used in double linked lists */ | 48 | /* lpfc_iocbqs are used in double linked lists */ |
49 | struct list_head list; | 49 | struct list_head list; |
50 | struct list_head clist; | 50 | struct list_head clist; |
51 | struct list_head dlist; | ||
51 | uint16_t iotag; /* pre-assigned IO tag */ | 52 | uint16_t iotag; /* pre-assigned IO tag */ |
52 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ | 53 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ |
53 | struct lpfc_cq_event cq_event; | 54 | struct lpfc_cq_event cq_event; |
@@ -64,6 +65,7 @@ struct lpfc_iocbq { | |||
64 | #define LPFC_EXCHANGE_BUSY 0x40 /* SLI4 hba reported XB in response */ | 65 | #define LPFC_EXCHANGE_BUSY 0x40 /* SLI4 hba reported XB in response */ |
65 | #define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */ | 66 | #define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */ |
66 | #define DSS_SECURITY_OP 0x100 /* security IO */ | 67 | #define DSS_SECURITY_OP 0x100 /* security IO */ |
68 | #define LPFC_IO_ON_Q 0x200 /* The IO is still on the TXCMPLQ */ | ||
67 | 69 | ||
68 | #define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */ | 70 | #define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */ |
69 | #define LPFC_FIP_ELS_ID_SHIFT 14 | 71 | #define LPFC_FIP_ELS_ID_SHIFT 14 |