diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:52:34 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:14 -0400 |
commit | 7054a606e6724674a5acd103ed74eacb02c73393 (patch) | |
tree | 271327c20a1e4bff9475ef7a9d98afd4644d6570 | |
parent | de0c5b32b50ef2673f4cd434b9c2732237d715dd (diff) |
[SCSI] lpfc 8.1.12 : Round 2 of Miscellaneous fixes
Round 2 of Miscellaneous fixes:
- Ensure we don't prematurely re-enable IRQs in lpfc_sli_abort_fcp_cmpl().
- Prevent freeing of iocb after IOCB_TIMEDOUT error.
- Added code to cleanup REG_LOGIN mailbox command when a LOGO is received.
- Fix offline window where more work can sneak in after clearing work_ha
- Use target reset instead of LU reset in bus_device_reset_handler
- Fixed system hangs due to leaked host_lock.
- Fixed NULL pointer dereference during I/O with LIP.
- Fixed false iocb timeout.
- Fixed name server query response handling.
- Change rport dev_loss_tmo value when user change lpfc HBA's dev_loss_tmo.
- Fixed a memory leak in lpfc_sli_wake_mbox_wait.
- Fixed check for dropped frames.
- Removed hba queue depth calculation based on device PCI IDs
- Change min cr_count value specified in comment to agree with setting
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 35 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 27 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 90 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 66 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 3 |
9 files changed, 168 insertions, 79 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 6aa91530fcde..b7193d1a90f6 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -27,10 +27,6 @@ struct lpfc_sli2_slim; | |||
27 | requests */ | 27 | requests */ |
28 | #define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact | 28 | #define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact |
29 | the NameServer before giving up. */ | 29 | the NameServer before giving up. */ |
30 | #define LPFC_DFT_HBA_Q_DEPTH 2048 /* max cmds per hba */ | ||
31 | #define LPFC_LC_HBA_Q_DEPTH 1024 /* max cmds per low cost hba */ | ||
32 | #define LPFC_LP101_HBA_Q_DEPTH 128 /* max cmds per low cost hba */ | ||
33 | |||
34 | #define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */ | 30 | #define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */ |
35 | #define LPFC_SG_SEG_CNT 64 /* sg element count per scsi cmnd */ | 31 | #define LPFC_SG_SEG_CNT 64 /* sg element count per scsi cmnd */ |
36 | #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ | 32 | #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index c0b02b11d88f..7811aaf114d5 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -828,6 +828,18 @@ lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val) | |||
828 | return -EINVAL; | 828 | return -EINVAL; |
829 | } | 829 | } |
830 | 830 | ||
831 | static void | ||
832 | lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba) | ||
833 | { | ||
834 | struct lpfc_nodelist *ndlp; | ||
835 | |||
836 | spin_lock_irq(phba->host->host_lock); | ||
837 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) | ||
838 | if (ndlp->rport) | ||
839 | ndlp->rport->dev_loss_tmo = phba->cfg_devloss_tmo; | ||
840 | spin_unlock_irq(phba->host->host_lock); | ||
841 | } | ||
842 | |||
831 | static int | 843 | static int |
832 | lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) | 844 | lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) |
833 | { | 845 | { |
@@ -843,6 +855,7 @@ lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) | |||
843 | if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { | 855 | if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { |
844 | phba->cfg_nodev_tmo = val; | 856 | phba->cfg_nodev_tmo = val; |
845 | phba->cfg_devloss_tmo = val; | 857 | phba->cfg_devloss_tmo = val; |
858 | lpfc_update_rport_devloss_tmo(phba); | ||
846 | return 0; | 859 | return 0; |
847 | } | 860 | } |
848 | 861 | ||
@@ -878,6 +891,7 @@ lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val) | |||
878 | phba->cfg_nodev_tmo = val; | 891 | phba->cfg_nodev_tmo = val; |
879 | phba->cfg_devloss_tmo = val; | 892 | phba->cfg_devloss_tmo = val; |
880 | phba->dev_loss_tmo_changed = 1; | 893 | phba->dev_loss_tmo_changed = 1; |
894 | lpfc_update_rport_devloss_tmo(phba); | ||
881 | return 0; | 895 | return 0; |
882 | } | 896 | } |
883 | 897 | ||
@@ -997,7 +1011,7 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support"); | |||
997 | /* | 1011 | /* |
998 | # lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing | 1012 | # lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing |
999 | # cr_delay (msec) or cr_count outstanding commands. cr_delay can take | 1013 | # cr_delay (msec) or cr_count outstanding commands. cr_delay can take |
1000 | # value [0,63]. cr_count can take value [0,255]. Default value of cr_delay | 1014 | # value [0,63]. cr_count can take value [1,255]. Default value of cr_delay |
1001 | # is 0. Default value of cr_count is 1. The cr_count feature is disabled if | 1015 | # is 0. Default value of cr_count is 1. The cr_count feature is disabled if |
1002 | # cr_delay is set to 0. | 1016 | # cr_delay is set to 0. |
1003 | */ | 1017 | */ |
@@ -1955,25 +1969,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
1955 | sizeof(struct fcp_rsp) + | 1969 | sizeof(struct fcp_rsp) + |
1956 | (phba->cfg_sg_seg_cnt * sizeof(struct ulp_bde64)); | 1970 | (phba->cfg_sg_seg_cnt * sizeof(struct ulp_bde64)); |
1957 | 1971 | ||
1958 | switch (phba->pcidev->device) { | ||
1959 | case PCI_DEVICE_ID_LP101: | ||
1960 | case PCI_DEVICE_ID_BSMB: | ||
1961 | case PCI_DEVICE_ID_ZSMB: | ||
1962 | phba->cfg_hba_queue_depth = LPFC_LP101_HBA_Q_DEPTH; | ||
1963 | break; | ||
1964 | case PCI_DEVICE_ID_RFLY: | ||
1965 | case PCI_DEVICE_ID_PFLY: | ||
1966 | case PCI_DEVICE_ID_BMID: | ||
1967 | case PCI_DEVICE_ID_ZMID: | ||
1968 | case PCI_DEVICE_ID_TFLY: | ||
1969 | phba->cfg_hba_queue_depth = LPFC_LC_HBA_Q_DEPTH; | ||
1970 | break; | ||
1971 | default: | ||
1972 | phba->cfg_hba_queue_depth = LPFC_DFT_HBA_Q_DEPTH; | ||
1973 | } | ||
1974 | 1972 | ||
1975 | if (phba->cfg_hba_queue_depth > lpfc_hba_queue_depth) | 1973 | lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); |
1976 | lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); | ||
1977 | 1974 | ||
1978 | return; | 1975 | return; |
1979 | } | 1976 | } |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 50f45339e0c0..48ae2355de69 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -334,22 +334,22 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size) | |||
334 | 334 | ||
335 | lpfc_set_disctmo(phba); | 335 | lpfc_set_disctmo(phba); |
336 | 336 | ||
337 | Cnt = Size > FCELSSIZE ? FCELSSIZE : Size; | ||
338 | 337 | ||
339 | list_add_tail(&head, &mp->list); | 338 | list_add_tail(&head, &mp->list); |
340 | list_for_each_entry_safe(mp, next_mp, &head, list) { | 339 | list_for_each_entry_safe(mp, next_mp, &head, list) { |
341 | mlast = mp; | 340 | mlast = mp; |
342 | 341 | ||
342 | Cnt = Size > FCELSSIZE ? FCELSSIZE : Size; | ||
343 | |||
343 | Size -= Cnt; | 344 | Size -= Cnt; |
344 | 345 | ||
345 | if (!ctptr) { | 346 | if (!ctptr) { |
346 | Cnt = FCELSSIZE; | ||
347 | ctptr = (uint32_t *) mlast->virt; | 347 | ctptr = (uint32_t *) mlast->virt; |
348 | } else | 348 | } else |
349 | Cnt -= 16; /* subtract length of CT header */ | 349 | Cnt -= 16; /* subtract length of CT header */ |
350 | 350 | ||
351 | /* Loop through entire NameServer list of DIDs */ | 351 | /* Loop through entire NameServer list of DIDs */ |
352 | while (Cnt) { | 352 | while (Cnt >= sizeof (uint32_t)) { |
353 | 353 | ||
354 | /* Get next DID from NameServer List */ | 354 | /* Get next DID from NameServer List */ |
355 | CTentry = *ctptr++; | 355 | CTentry = *ctptr++; |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 14266dfb35db..4d9e7f50c189 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -3214,7 +3214,7 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
3214 | IOCB_t *cmd = NULL; | 3214 | IOCB_t *cmd = NULL; |
3215 | struct lpfc_dmabuf *pcmd; | 3215 | struct lpfc_dmabuf *pcmd; |
3216 | uint32_t *elscmd; | 3216 | uint32_t *elscmd; |
3217 | uint32_t els_command; | 3217 | uint32_t els_command=0; |
3218 | uint32_t timeout; | 3218 | uint32_t timeout; |
3219 | uint32_t remote_ID; | 3219 | uint32_t remote_ID; |
3220 | 3220 | ||
@@ -3233,12 +3233,16 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
3233 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | 3233 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { |
3234 | cmd = &piocb->iocb; | 3234 | cmd = &piocb->iocb; |
3235 | 3235 | ||
3236 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) { | 3236 | if ((piocb->iocb_flag & LPFC_IO_LIBDFC) || |
3237 | (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) || | ||
3238 | (piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) { | ||
3237 | continue; | 3239 | continue; |
3238 | } | 3240 | } |
3239 | pcmd = (struct lpfc_dmabuf *) piocb->context2; | 3241 | pcmd = (struct lpfc_dmabuf *) piocb->context2; |
3240 | elscmd = (uint32_t *) (pcmd->virt); | 3242 | if (pcmd) { |
3241 | els_command = *elscmd; | 3243 | elscmd = (uint32_t *) (pcmd->virt); |
3244 | els_command = *elscmd; | ||
3245 | } | ||
3242 | 3246 | ||
3243 | if ((els_command == ELS_CMD_FARP) | 3247 | if ((els_command == ELS_CMD_FARP) |
3244 | || (els_command == ELS_CMD_FARPR)) { | 3248 | || (els_command == ELS_CMD_FARPR)) { |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 5f013f1cdead..6449ac8fca24 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1375,8 +1375,6 @@ lpfc_offline(struct lpfc_hba * phba) | |||
1375 | 1375 | ||
1376 | /* stop all timers associated with this hba */ | 1376 | /* stop all timers associated with this hba */ |
1377 | lpfc_stop_timer(phba); | 1377 | lpfc_stop_timer(phba); |
1378 | phba->work_hba_events = 0; | ||
1379 | phba->work_ha = 0; | ||
1380 | 1378 | ||
1381 | lpfc_printf_log(phba, | 1379 | lpfc_printf_log(phba, |
1382 | KERN_WARNING, | 1380 | KERN_WARNING, |
@@ -1389,6 +1387,8 @@ lpfc_offline(struct lpfc_hba * phba) | |||
1389 | lpfc_sli_hba_down(phba); | 1387 | lpfc_sli_hba_down(phba); |
1390 | lpfc_cleanup(phba); | 1388 | lpfc_cleanup(phba); |
1391 | spin_lock_irqsave(phba->host->host_lock, iflag); | 1389 | spin_lock_irqsave(phba->host->host_lock, iflag); |
1390 | phba->work_hba_events = 0; | ||
1391 | phba->work_ha = 0; | ||
1392 | phba->fc_flag |= FC_OFFLINE_MODE; | 1392 | phba->fc_flag |= FC_OFFLINE_MODE; |
1393 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | 1393 | spin_unlock_irqrestore(phba->host->host_lock, iflag); |
1394 | } | 1394 | } |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 5595c612e223..789a12dc986b 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -1019,9 +1019,36 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba, | |||
1019 | uint32_t evt) | 1019 | uint32_t evt) |
1020 | { | 1020 | { |
1021 | struct lpfc_iocbq *cmdiocb; | 1021 | struct lpfc_iocbq *cmdiocb; |
1022 | LPFC_MBOXQ_t *mb; | ||
1023 | LPFC_MBOXQ_t *nextmb; | ||
1024 | struct lpfc_dmabuf *mp; | ||
1022 | 1025 | ||
1023 | cmdiocb = (struct lpfc_iocbq *) arg; | 1026 | cmdiocb = (struct lpfc_iocbq *) arg; |
1024 | 1027 | ||
1028 | /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ | ||
1029 | if ((mb = phba->sli.mbox_active)) { | ||
1030 | if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && | ||
1031 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { | ||
1032 | mb->context2 = NULL; | ||
1033 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1037 | spin_lock_irq(phba->host->host_lock); | ||
1038 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { | ||
1039 | if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && | ||
1040 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { | ||
1041 | mp = (struct lpfc_dmabuf *) (mb->context1); | ||
1042 | if (mp) { | ||
1043 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
1044 | kfree(mp); | ||
1045 | } | ||
1046 | list_del(&mb->list); | ||
1047 | mempool_free(mb, phba->mbox_mem_pool); | ||
1048 | } | ||
1049 | } | ||
1050 | spin_unlock_irq(phba->host->host_lock); | ||
1051 | |||
1025 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | 1052 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); |
1026 | return ndlp->nlp_state; | 1053 | return ndlp->nlp_state; |
1027 | } | 1054 | } |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 28dbd6be72ee..efd1cf638b8c 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -292,13 +292,13 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) | |||
292 | } | 292 | } |
293 | 293 | ||
294 | static void | 294 | static void |
295 | lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) | 295 | lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb) |
296 | { | 296 | { |
297 | struct scsi_cmnd *cmnd = lpfc_cmd->pCmd; | 297 | struct scsi_cmnd *cmnd = lpfc_cmd->pCmd; |
298 | struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd; | 298 | struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd; |
299 | struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; | 299 | struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; |
300 | struct lpfc_hba *phba = lpfc_cmd->scsi_hba; | 300 | struct lpfc_hba *phba = lpfc_cmd->scsi_hba; |
301 | uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm; | 301 | uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm; |
302 | uint32_t resp_info = fcprsp->rspStatus2; | 302 | uint32_t resp_info = fcprsp->rspStatus2; |
303 | uint32_t scsi_status = fcprsp->rspStatus3; | 303 | uint32_t scsi_status = fcprsp->rspStatus3; |
304 | uint32_t *lp; | 304 | uint32_t *lp; |
@@ -360,6 +360,24 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) | |||
360 | fcpi_parm, cmnd->cmnd[0], cmnd->underflow); | 360 | fcpi_parm, cmnd->cmnd[0], cmnd->underflow); |
361 | 361 | ||
362 | /* | 362 | /* |
363 | * If there is an under run check if under run reported by | ||
364 | * storage array is same as the under run reported by HBA. | ||
365 | * If this is not same, there is a dropped frame. | ||
366 | */ | ||
367 | if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) && | ||
368 | fcpi_parm && | ||
369 | (cmnd->resid != fcpi_parm)) { | ||
370 | lpfc_printf_log(phba, KERN_WARNING, | ||
371 | LOG_FCP | LOG_FCP_ERROR, | ||
372 | "%d:0735 FCP Read Check Error and Underrun " | ||
373 | "Data: x%x x%x x%x x%x\n", phba->brd_no, | ||
374 | be32_to_cpu(fcpcmd->fcpDl), | ||
375 | cmnd->resid, | ||
376 | fcpi_parm, cmnd->cmnd[0]); | ||
377 | cmnd->resid = cmnd->request_bufflen; | ||
378 | host_status = DID_ERROR; | ||
379 | } | ||
380 | /* | ||
363 | * The cmnd->underflow is the minimum number of bytes that must | 381 | * The cmnd->underflow is the minimum number of bytes that must |
364 | * be transfered for this command. Provided a sense condition | 382 | * be transfered for this command. Provided a sense condition |
365 | * is not present, make sure the actual amount transferred is at | 383 | * is not present, make sure the actual amount transferred is at |
@@ -439,7 +457,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
439 | switch (lpfc_cmd->status) { | 457 | switch (lpfc_cmd->status) { |
440 | case IOSTAT_FCP_RSP_ERROR: | 458 | case IOSTAT_FCP_RSP_ERROR: |
441 | /* Call FCP RSP handler to determine result */ | 459 | /* Call FCP RSP handler to determine result */ |
442 | lpfc_handle_fcp_err(lpfc_cmd); | 460 | lpfc_handle_fcp_err(lpfc_cmd,pIocbOut); |
443 | break; | 461 | break; |
444 | case IOSTAT_NPORT_BSY: | 462 | case IOSTAT_NPORT_BSY: |
445 | case IOSTAT_FABRIC_BSY: | 463 | case IOSTAT_FABRIC_BSY: |
@@ -673,6 +691,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba, | |||
673 | return (1); | 691 | return (1); |
674 | } | 692 | } |
675 | 693 | ||
694 | static void | ||
695 | lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba, | ||
696 | struct lpfc_iocbq *cmdiocbq, | ||
697 | struct lpfc_iocbq *rspiocbq) | ||
698 | { | ||
699 | struct lpfc_scsi_buf *lpfc_cmd = | ||
700 | (struct lpfc_scsi_buf *) cmdiocbq->context1; | ||
701 | if (lpfc_cmd) | ||
702 | lpfc_release_scsi_buf(phba, lpfc_cmd); | ||
703 | return; | ||
704 | } | ||
705 | |||
676 | static int | 706 | static int |
677 | lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, | 707 | lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, |
678 | unsigned tgt_id, unsigned int lun, | 708 | unsigned tgt_id, unsigned int lun, |
@@ -709,8 +739,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, | |||
709 | &phba->sli.ring[phba->sli.fcp_ring], | 739 | &phba->sli.ring[phba->sli.fcp_ring], |
710 | iocbq, iocbqrsp, lpfc_cmd->timeout); | 740 | iocbq, iocbqrsp, lpfc_cmd->timeout); |
711 | if (ret != IOCB_SUCCESS) { | 741 | if (ret != IOCB_SUCCESS) { |
742 | if (ret == IOCB_TIMEDOUT) | ||
743 | iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; | ||
712 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; | 744 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; |
713 | ret = FAILED; | ||
714 | } else { | 745 | } else { |
715 | ret = SUCCESS; | 746 | ret = SUCCESS; |
716 | lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4]; | 747 | lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4]; |
@@ -977,7 +1008,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
977 | } | 1008 | } |
978 | 1009 | ||
979 | static int | 1010 | static int |
980 | lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | 1011 | lpfc_device_reset_handler(struct scsi_cmnd *cmnd) |
981 | { | 1012 | { |
982 | struct Scsi_Host *shost = cmnd->device->host; | 1013 | struct Scsi_Host *shost = cmnd->device->host; |
983 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; | 1014 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; |
@@ -987,6 +1018,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
987 | struct lpfc_nodelist *pnode = rdata->pnode; | 1018 | struct lpfc_nodelist *pnode = rdata->pnode; |
988 | uint32_t cmd_result = 0, cmd_status = 0; | 1019 | uint32_t cmd_result = 0, cmd_status = 0; |
989 | int ret = FAILED; | 1020 | int ret = FAILED; |
1021 | int iocb_status = IOCB_SUCCESS; | ||
990 | int cnt, loopcnt; | 1022 | int cnt, loopcnt; |
991 | 1023 | ||
992 | lpfc_block_error_handler(cmnd); | 1024 | lpfc_block_error_handler(cmnd); |
@@ -998,7 +1030,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
998 | */ | 1030 | */ |
999 | while ( 1 ) { | 1031 | while ( 1 ) { |
1000 | if (!pnode) | 1032 | if (!pnode) |
1001 | return FAILED; | 1033 | goto out; |
1002 | 1034 | ||
1003 | if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { | 1035 | if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { |
1004 | spin_unlock_irq(phba->host->host_lock); | 1036 | spin_unlock_irq(phba->host->host_lock); |
@@ -1016,7 +1048,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1016 | } | 1048 | } |
1017 | pnode = rdata->pnode; | 1049 | pnode = rdata->pnode; |
1018 | if (!pnode) | 1050 | if (!pnode) |
1019 | return FAILED; | 1051 | goto out; |
1020 | } | 1052 | } |
1021 | if (pnode->nlp_state == NLP_STE_MAPPED_NODE) | 1053 | if (pnode->nlp_state == NLP_STE_MAPPED_NODE) |
1022 | break; | 1054 | break; |
@@ -1031,7 +1063,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1031 | lpfc_cmd->rdata = rdata; | 1063 | lpfc_cmd->rdata = rdata; |
1032 | 1064 | ||
1033 | ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun, | 1065 | ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun, |
1034 | FCP_LUN_RESET); | 1066 | FCP_TARGET_RESET); |
1035 | if (!ret) | 1067 | if (!ret) |
1036 | goto out_free_scsi_buf; | 1068 | goto out_free_scsi_buf; |
1037 | 1069 | ||
@@ -1043,16 +1075,21 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1043 | goto out_free_scsi_buf; | 1075 | goto out_free_scsi_buf; |
1044 | 1076 | ||
1045 | lpfc_printf_log(phba, KERN_INFO, LOG_FCP, | 1077 | lpfc_printf_log(phba, KERN_INFO, LOG_FCP, |
1046 | "%d:0703 Issue LUN Reset to TGT %d LUN %d " | 1078 | "%d:0703 Issue target reset to TGT %d LUN %d rpi x%x " |
1047 | "Data: x%x x%x\n", phba->brd_no, cmnd->device->id, | 1079 | "nlp_flag x%x\n", phba->brd_no, cmnd->device->id, |
1048 | cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag); | 1080 | cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag); |
1049 | 1081 | ||
1050 | ret = lpfc_sli_issue_iocb_wait(phba, | 1082 | iocb_status = lpfc_sli_issue_iocb_wait(phba, |
1051 | &phba->sli.ring[phba->sli.fcp_ring], | 1083 | &phba->sli.ring[phba->sli.fcp_ring], |
1052 | iocbq, iocbqrsp, lpfc_cmd->timeout); | 1084 | iocbq, iocbqrsp, lpfc_cmd->timeout); |
1053 | if (ret == IOCB_SUCCESS) | ||
1054 | ret = SUCCESS; | ||
1055 | 1085 | ||
1086 | if (iocb_status == IOCB_TIMEDOUT) | ||
1087 | iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; | ||
1088 | |||
1089 | if (iocb_status == IOCB_SUCCESS) | ||
1090 | ret = SUCCESS; | ||
1091 | else | ||
1092 | ret = iocb_status; | ||
1056 | 1093 | ||
1057 | cmd_result = iocbqrsp->iocb.un.ulpWord[4]; | 1094 | cmd_result = iocbqrsp->iocb.un.ulpWord[4]; |
1058 | cmd_status = iocbqrsp->iocb.ulpStatus; | 1095 | cmd_status = iocbqrsp->iocb.ulpStatus; |
@@ -1090,18 +1127,19 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1090 | 1127 | ||
1091 | if (cnt) { | 1128 | if (cnt) { |
1092 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 1129 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
1093 | "%d:0719 LUN Reset I/O flush failure: cnt x%x\n", | 1130 | "%d:0719 device reset I/O flush failure: cnt x%x\n", |
1094 | phba->brd_no, cnt); | 1131 | phba->brd_no, cnt); |
1095 | ret = FAILED; | 1132 | ret = FAILED; |
1096 | } | 1133 | } |
1097 | 1134 | ||
1098 | out_free_scsi_buf: | 1135 | out_free_scsi_buf: |
1099 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 1136 | if (iocb_status != IOCB_TIMEDOUT) { |
1100 | 1137 | lpfc_release_scsi_buf(phba, lpfc_cmd); | |
1138 | } | ||
1101 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 1139 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
1102 | "%d:0713 SCSI layer issued LUN reset (%d, %d) " | 1140 | "%d:0713 SCSI layer issued device reset (%d, %d) " |
1103 | "Data: x%x x%x x%x\n", | 1141 | "return x%x status x%x result x%x\n", |
1104 | phba->brd_no, cmnd->device->id,cmnd->device->lun, | 1142 | phba->brd_no, cmnd->device->id, cmnd->device->lun, |
1105 | ret, cmd_status, cmd_result); | 1143 | ret, cmd_status, cmd_result); |
1106 | 1144 | ||
1107 | out: | 1145 | out: |
@@ -1110,7 +1148,7 @@ out: | |||
1110 | } | 1148 | } |
1111 | 1149 | ||
1112 | static int | 1150 | static int |
1113 | lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | 1151 | lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) |
1114 | { | 1152 | { |
1115 | struct Scsi_Host *shost = cmnd->device->host; | 1153 | struct Scsi_Host *shost = cmnd->device->host; |
1116 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; | 1154 | struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; |
@@ -1155,13 +1193,17 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
1155 | "%d:0700 Bus Reset on target %d failed\n", | 1193 | "%d:0700 Bus Reset on target %d failed\n", |
1156 | phba->brd_no, i); | 1194 | phba->brd_no, i); |
1157 | err_count++; | 1195 | err_count++; |
1196 | break; | ||
1158 | } | 1197 | } |
1159 | } | 1198 | } |
1160 | 1199 | ||
1200 | if (ret != IOCB_TIMEDOUT) | ||
1201 | lpfc_release_scsi_buf(phba, lpfc_cmd); | ||
1202 | |||
1161 | if (err_count == 0) | 1203 | if (err_count == 0) |
1162 | ret = SUCCESS; | 1204 | ret = SUCCESS; |
1163 | 1205 | else | |
1164 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 1206 | ret = FAILED; |
1165 | 1207 | ||
1166 | /* | 1208 | /* |
1167 | * All outstanding txcmplq I/Os should have been aborted by | 1209 | * All outstanding txcmplq I/Os should have been aborted by |
@@ -1302,8 +1344,8 @@ struct scsi_host_template lpfc_template = { | |||
1302 | .info = lpfc_info, | 1344 | .info = lpfc_info, |
1303 | .queuecommand = lpfc_queuecommand, | 1345 | .queuecommand = lpfc_queuecommand, |
1304 | .eh_abort_handler = lpfc_abort_handler, | 1346 | .eh_abort_handler = lpfc_abort_handler, |
1305 | .eh_device_reset_handler= lpfc_reset_lun_handler, | 1347 | .eh_device_reset_handler= lpfc_device_reset_handler, |
1306 | .eh_bus_reset_handler = lpfc_reset_bus_handler, | 1348 | .eh_bus_reset_handler = lpfc_bus_reset_handler, |
1307 | .slave_alloc = lpfc_slave_alloc, | 1349 | .slave_alloc = lpfc_slave_alloc, |
1308 | .slave_configure = lpfc_slave_configure, | 1350 | .slave_configure = lpfc_slave_configure, |
1309 | .slave_destroy = lpfc_slave_destroy, | 1351 | .slave_destroy = lpfc_slave_destroy, |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 16825243e603..dba94c68feb1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -528,6 +528,7 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) | |||
528 | * If pdone_q is empty, the driver thread gave up waiting and | 528 | * If pdone_q is empty, the driver thread gave up waiting and |
529 | * continued running. | 529 | * continued running. |
530 | */ | 530 | */ |
531 | pmboxq->mbox_flag |= LPFC_MBX_WAKE; | ||
531 | pdone_q = (wait_queue_head_t *) pmboxq->context1; | 532 | pdone_q = (wait_queue_head_t *) pmboxq->context1; |
532 | if (pdone_q) | 533 | if (pdone_q) |
533 | wake_up_interruptible(pdone_q); | 534 | wake_up_interruptible(pdone_q); |
@@ -538,11 +539,32 @@ void | |||
538 | lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | 539 | lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) |
539 | { | 540 | { |
540 | struct lpfc_dmabuf *mp; | 541 | struct lpfc_dmabuf *mp; |
542 | uint16_t rpi; | ||
543 | int rc; | ||
544 | |||
541 | mp = (struct lpfc_dmabuf *) (pmb->context1); | 545 | mp = (struct lpfc_dmabuf *) (pmb->context1); |
546 | |||
542 | if (mp) { | 547 | if (mp) { |
543 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 548 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
544 | kfree(mp); | 549 | kfree(mp); |
545 | } | 550 | } |
551 | |||
552 | /* | ||
553 | * If a REG_LOGIN succeeded after node is destroyed or node | ||
554 | * is in re-discovery driver need to cleanup the RPI. | ||
555 | */ | ||
556 | if (!(phba->fc_flag & FC_UNLOADING) && | ||
557 | (pmb->mb.mbxCommand == MBX_REG_LOGIN64) && | ||
558 | (!pmb->mb.mbxStatus)) { | ||
559 | |||
560 | rpi = pmb->mb.un.varWords[0]; | ||
561 | lpfc_unreg_login(phba, rpi, pmb); | ||
562 | pmb->mbox_cmpl=lpfc_sli_def_mbox_cmpl; | ||
563 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | ||
564 | if (rc != MBX_NOT_FINISHED) | ||
565 | return; | ||
566 | } | ||
567 | |||
546 | mempool_free( pmb, phba->mbox_mem_pool); | 568 | mempool_free( pmb, phba->mbox_mem_pool); |
547 | return; | 569 | return; |
548 | } | 570 | } |
@@ -2862,9 +2884,11 @@ void | |||
2862 | lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 2884 | lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, |
2863 | struct lpfc_iocbq * rspiocb) | 2885 | struct lpfc_iocbq * rspiocb) |
2864 | { | 2886 | { |
2865 | spin_lock_irq(phba->host->host_lock); | 2887 | unsigned long iflags; |
2888 | |||
2889 | spin_lock_irqsave(phba->host->host_lock, iflags); | ||
2866 | lpfc_sli_release_iocbq(phba, cmdiocb); | 2890 | lpfc_sli_release_iocbq(phba, cmdiocb); |
2867 | spin_unlock_irq(phba->host->host_lock); | 2891 | spin_unlock_irqrestore(phba->host->host_lock, iflags); |
2868 | return; | 2892 | return; |
2869 | } | 2893 | } |
2870 | 2894 | ||
@@ -2987,22 +3011,22 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba, | |||
2987 | timeout_req); | 3011 | timeout_req); |
2988 | spin_lock_irq(phba->host->host_lock); | 3012 | spin_lock_irq(phba->host->host_lock); |
2989 | 3013 | ||
2990 | if (timeleft == 0) { | 3014 | if (piocb->iocb_flag & LPFC_IO_WAKE) { |
3015 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
3016 | "%d:0331 IOCB wake signaled\n", | ||
3017 | phba->brd_no); | ||
3018 | } else if (timeleft == 0) { | ||
2991 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 3019 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
2992 | "%d:0338 IOCB wait timeout error - no " | 3020 | "%d:0338 IOCB wait timeout error - no " |
2993 | "wake response Data x%x\n", | 3021 | "wake response Data x%x\n", |
2994 | phba->brd_no, timeout); | 3022 | phba->brd_no, timeout); |
2995 | retval = IOCB_TIMEDOUT; | 3023 | retval = IOCB_TIMEDOUT; |
2996 | } else if (!(piocb->iocb_flag & LPFC_IO_WAKE)) { | 3024 | } else { |
2997 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 3025 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
2998 | "%d:0330 IOCB wake NOT set, " | 3026 | "%d:0330 IOCB wake NOT set, " |
2999 | "Data x%x x%lx\n", phba->brd_no, | 3027 | "Data x%x x%lx\n", phba->brd_no, |
3000 | timeout, (timeleft / jiffies)); | 3028 | timeout, (timeleft / jiffies)); |
3001 | retval = IOCB_TIMEDOUT; | 3029 | retval = IOCB_TIMEDOUT; |
3002 | } else { | ||
3003 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
3004 | "%d:0331 IOCB wake signaled\n", | ||
3005 | phba->brd_no); | ||
3006 | } | 3030 | } |
3007 | } else { | 3031 | } else { |
3008 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 3032 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
@@ -3031,8 +3055,6 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, | |||
3031 | uint32_t timeout) | 3055 | uint32_t timeout) |
3032 | { | 3056 | { |
3033 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); | 3057 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); |
3034 | DECLARE_WAITQUEUE(wq_entry, current); | ||
3035 | uint32_t timeleft = 0; | ||
3036 | int retval; | 3058 | int retval; |
3037 | 3059 | ||
3038 | /* The caller must leave context1 empty. */ | 3060 | /* The caller must leave context1 empty. */ |
@@ -3045,27 +3067,25 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, | |||
3045 | /* setup context field to pass wait_queue pointer to wake function */ | 3067 | /* setup context field to pass wait_queue pointer to wake function */ |
3046 | pmboxq->context1 = &done_q; | 3068 | pmboxq->context1 = &done_q; |
3047 | 3069 | ||
3048 | /* start to sleep before we wait, to avoid races */ | ||
3049 | set_current_state(TASK_INTERRUPTIBLE); | ||
3050 | add_wait_queue(&done_q, &wq_entry); | ||
3051 | |||
3052 | /* now issue the command */ | 3070 | /* now issue the command */ |
3053 | retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | 3071 | retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); |
3054 | 3072 | ||
3055 | if (retval == MBX_BUSY || retval == MBX_SUCCESS) { | 3073 | if (retval == MBX_BUSY || retval == MBX_SUCCESS) { |
3056 | timeleft = schedule_timeout(timeout * HZ); | 3074 | wait_event_interruptible_timeout(done_q, |
3075 | pmboxq->mbox_flag & LPFC_MBX_WAKE, | ||
3076 | timeout * HZ); | ||
3077 | |||
3057 | pmboxq->context1 = NULL; | 3078 | pmboxq->context1 = NULL; |
3058 | /* if schedule_timeout returns 0, we timed out and were not | 3079 | /* |
3059 | woken up */ | 3080 | * if LPFC_MBX_WAKE flag is set the mailbox is completed |
3060 | if ((timeleft == 0) || signal_pending(current)) | 3081 | * else do not free the resources. |
3061 | retval = MBX_TIMEOUT; | 3082 | */ |
3062 | else | 3083 | if (pmboxq->mbox_flag & LPFC_MBX_WAKE) |
3063 | retval = MBX_SUCCESS; | 3084 | retval = MBX_SUCCESS; |
3085 | else | ||
3086 | retval = MBX_TIMEOUT; | ||
3064 | } | 3087 | } |
3065 | 3088 | ||
3066 | |||
3067 | set_current_state(TASK_RUNNING); | ||
3068 | remove_wait_queue(&done_q, &wq_entry); | ||
3069 | return retval; | 3089 | return retval; |
3070 | } | 3090 | } |
3071 | 3091 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 10dd5a9ddfd3..eb6a689e52e1 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -68,6 +68,8 @@ struct lpfc_iocbq { | |||
68 | #define IOCB_ERROR 2 | 68 | #define IOCB_ERROR 2 |
69 | #define IOCB_TIMEDOUT 3 | 69 | #define IOCB_TIMEDOUT 3 |
70 | 70 | ||
71 | #define LPFC_MBX_WAKE 1 | ||
72 | |||
71 | typedef struct lpfcMboxq { | 73 | typedef struct lpfcMboxq { |
72 | /* MBOXQs are used in single linked lists */ | 74 | /* MBOXQs are used in single linked lists */ |
73 | struct list_head list; /* ptr to next mailbox command */ | 75 | struct list_head list; /* ptr to next mailbox command */ |
@@ -76,6 +78,7 @@ typedef struct lpfcMboxq { | |||
76 | void *context2; /* caller context information */ | 78 | void *context2; /* caller context information */ |
77 | 79 | ||
78 | void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *); | 80 | void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *); |
81 | uint8_t mbox_flag; | ||
79 | 82 | ||
80 | } LPFC_MBOXQ_t; | 83 | } LPFC_MBOXQ_t; |
81 | 84 | ||