diff options
author | James.Smart@Emulex.Com <James.Smart@Emulex.Com> | 2005-11-28 11:42:05 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-12-13 20:26:47 -0500 |
commit | 6175c02a0b12f92c03b56c756c4f1e131ae1456c (patch) | |
tree | cee1a84d2c98d52456ceffc3d5d64eadc024266b /drivers | |
parent | 63c59c3b8ff444b771a245f59935c0202ece963b (diff) |
[SCSI] lpfc 8.1.1 : Fixes to error handlers
- Release task management command before counting outstanding commands.
TMF was being erroneously counted as an active outstanding command.
- Serialize EH calls and block requests when EH function is running.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 104 |
3 files changed, 70 insertions, 37 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 3062b39fbdb9..dc73a2f8f12c 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -167,6 +167,7 @@ struct lpfc_hba { | |||
167 | dma_addr_t slim2p_mapping; | 167 | dma_addr_t slim2p_mapping; |
168 | uint16_t pci_cfg_value; | 168 | uint16_t pci_cfg_value; |
169 | 169 | ||
170 | struct semaphore hba_can_block; | ||
170 | uint32_t hba_state; | 171 | uint32_t hba_state; |
171 | 172 | ||
172 | #define LPFC_INIT_START 1 /* Initial state after board reset */ | 173 | #define LPFC_INIT_START 1 /* Initial state after board reset */ |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 4d4e217edd84..dfd59d21ec49 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1345,7 +1345,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1345 | goto out_put_host; | 1345 | goto out_put_host; |
1346 | 1346 | ||
1347 | host->unique_id = phba->brd_no; | 1347 | host->unique_id = phba->brd_no; |
1348 | 1348 | init_MUTEX(&phba->hba_can_block); | |
1349 | INIT_LIST_HEAD(&phba->ctrspbuflist); | 1349 | INIT_LIST_HEAD(&phba->ctrspbuflist); |
1350 | INIT_LIST_HEAD(&phba->rnidrspbuflist); | 1350 | INIT_LIST_HEAD(&phba->rnidrspbuflist); |
1351 | INIT_LIST_HEAD(&phba->freebufList); | 1351 | INIT_LIST_HEAD(&phba->freebufList); |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index a4d8455de446..7dc7810b7482 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -41,6 +41,20 @@ | |||
41 | #define LPFC_ABORT_WAIT 2 | 41 | #define LPFC_ABORT_WAIT 2 |
42 | 42 | ||
43 | 43 | ||
44 | static inline void | ||
45 | lpfc_block_requests(struct lpfc_hba * phba) | ||
46 | { | ||
47 | down(&phba->hba_can_block); | ||
48 | scsi_block_requests(phba->host); | ||
49 | } | ||
50 | |||
51 | static inline void | ||
52 | lpfc_unblock_requests(struct lpfc_hba * phba) | ||
53 | { | ||
54 | scsi_unblock_requests(phba->host); | ||
55 | up(&phba->hba_can_block); | ||
56 | } | ||
57 | |||
44 | /* | 58 | /* |
45 | * This routine allocates a scsi buffer, which contains all the necessary | 59 | * This routine allocates a scsi buffer, which contains all the necessary |
46 | * information needed to initiate a SCSI I/O. The non-DMAable buffer region | 60 | * information needed to initiate a SCSI I/O. The non-DMAable buffer region |
@@ -774,6 +788,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
774 | unsigned int loop_count = 0; | 788 | unsigned int loop_count = 0; |
775 | int ret = SUCCESS; | 789 | int ret = SUCCESS; |
776 | 790 | ||
791 | lpfc_block_requests(phba); | ||
777 | spin_lock_irq(shost->host_lock); | 792 | spin_lock_irq(shost->host_lock); |
778 | 793 | ||
779 | lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; | 794 | lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; |
@@ -853,6 +868,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
853 | cmnd->device->lun, cmnd->serial_number); | 868 | cmnd->device->lun, cmnd->serial_number); |
854 | 869 | ||
855 | spin_unlock_irq(shost->host_lock); | 870 | spin_unlock_irq(shost->host_lock); |
871 | lpfc_unblock_requests(phba); | ||
856 | 872 | ||
857 | return ret; | 873 | return ret; |
858 | } | 874 | } |
@@ -866,9 +882,11 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
866 | struct lpfc_iocbq *iocbq, *iocbqrsp; | 882 | struct lpfc_iocbq *iocbq, *iocbqrsp; |
867 | struct lpfc_rport_data *rdata = cmnd->device->hostdata; | 883 | struct lpfc_rport_data *rdata = cmnd->device->hostdata; |
868 | struct lpfc_nodelist *pnode = rdata->pnode; | 884 | struct lpfc_nodelist *pnode = rdata->pnode; |
885 | uint32_t cmd_result = 0, cmd_status = 0; | ||
869 | int ret = FAILED; | 886 | int ret = FAILED; |
870 | int cnt, loopcnt; | 887 | int cnt, loopcnt; |
871 | 888 | ||
889 | lpfc_block_requests(phba); | ||
872 | spin_lock_irq(shost->host_lock); | 890 | spin_lock_irq(shost->host_lock); |
873 | /* | 891 | /* |
874 | * If target is not in a MAPPED state, delay the reset until | 892 | * If target is not in a MAPPED state, delay the reset until |
@@ -912,26 +930,28 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
912 | if (ret == IOCB_SUCCESS) | 930 | if (ret == IOCB_SUCCESS) |
913 | ret = SUCCESS; | 931 | ret = SUCCESS; |
914 | 932 | ||
915 | lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4]; | 933 | |
916 | lpfc_cmd->status = iocbqrsp->iocb.ulpStatus; | 934 | cmd_result = iocbqrsp->iocb.un.ulpWord[4]; |
917 | if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT) | 935 | cmd_status = iocbqrsp->iocb.ulpStatus; |
918 | if (lpfc_cmd->result & IOERR_DRVR_MASK) | 936 | |
919 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; | 937 | lpfc_sli_release_iocbq(phba, iocbqrsp); |
938 | lpfc_release_scsi_buf(phba, lpfc_cmd); | ||
920 | 939 | ||
921 | /* | 940 | /* |
922 | * All outstanding txcmplq I/Os should have been aborted by the target. | 941 | * All outstanding txcmplq I/Os should have been aborted by the device. |
923 | * Unfortunately, some targets do not abide by this forcing the driver | 942 | * Unfortunately, some targets do not abide by this forcing the driver |
924 | * to double check. | 943 | * to double check. |
925 | */ | 944 | */ |
926 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 945 | cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], |
927 | cmnd->device->id, cmnd->device->lun, 0, | 946 | cmnd->device->id, cmnd->device->lun, |
928 | LPFC_CTX_LUN); | 947 | LPFC_CTX_LUN); |
929 | 948 | if (cnt) | |
949 | lpfc_sli_abort_iocb(phba, | ||
950 | &phba->sli.ring[phba->sli.fcp_ring], | ||
951 | cmnd->device->id, cmnd->device->lun, | ||
952 | 0, LPFC_CTX_LUN); | ||
930 | loopcnt = 0; | 953 | loopcnt = 0; |
931 | while((cnt = lpfc_sli_sum_iocb(phba, | 954 | while(cnt) { |
932 | &phba->sli.ring[phba->sli.fcp_ring], | ||
933 | cmnd->device->id, cmnd->device->lun, | ||
934 | LPFC_CTX_LUN))) { | ||
935 | spin_unlock_irq(phba->host->host_lock); | 955 | spin_unlock_irq(phba->host->host_lock); |
936 | schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); | 956 | schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); |
937 | spin_lock_irq(phba->host->host_lock); | 957 | spin_lock_irq(phba->host->host_lock); |
@@ -939,6 +959,11 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
939 | if (++loopcnt | 959 | if (++loopcnt |
940 | > (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT) | 960 | > (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT) |
941 | break; | 961 | break; |
962 | |||
963 | cnt = lpfc_sli_sum_iocb(phba, | ||
964 | &phba->sli.ring[phba->sli.fcp_ring], | ||
965 | cmnd->device->id, cmnd->device->lun, | ||
966 | LPFC_CTX_LUN); | ||
942 | } | 967 | } |
943 | 968 | ||
944 | if (cnt) { | 969 | if (cnt) { |
@@ -948,18 +973,16 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
948 | ret = FAILED; | 973 | ret = FAILED; |
949 | } | 974 | } |
950 | 975 | ||
951 | lpfc_sli_release_iocbq(phba, iocbqrsp); | ||
952 | |||
953 | out_free_scsi_buf: | 976 | out_free_scsi_buf: |
954 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 977 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
955 | "%d:0713 SCSI layer issued LUN reset (%d, %d) " | 978 | "%d:0713 SCSI layer issued LUN reset (%d, %d) " |
956 | "Data: x%x x%x x%x\n", | 979 | "Data: x%x x%x x%x\n", |
957 | phba->brd_no, lpfc_cmd->pCmd->device->id, | 980 | phba->brd_no, cmnd->device->id,cmnd->device->lun, |
958 | lpfc_cmd->pCmd->device->lun, ret, lpfc_cmd->status, | 981 | ret, cmd_status, cmd_result); |
959 | lpfc_cmd->result); | 982 | |
960 | lpfc_release_scsi_buf(phba, lpfc_cmd); | ||
961 | out: | 983 | out: |
962 | spin_unlock_irq(shost->host_lock); | 984 | spin_unlock_irq(shost->host_lock); |
985 | lpfc_unblock_requests(phba); | ||
963 | return ret; | 986 | return ret; |
964 | } | 987 | } |
965 | 988 | ||
@@ -975,6 +998,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
975 | unsigned int midlayer_id = 0; | 998 | unsigned int midlayer_id = 0; |
976 | struct lpfc_scsi_buf * lpfc_cmd; | 999 | struct lpfc_scsi_buf * lpfc_cmd; |
977 | 1000 | ||
1001 | lpfc_block_requests(phba); | ||
978 | spin_lock_irq(shost->host_lock); | 1002 | spin_lock_irq(shost->host_lock); |
979 | 1003 | ||
980 | lpfc_cmd = lpfc_sli_get_scsi_buf (phba); | 1004 | lpfc_cmd = lpfc_sli_get_scsi_buf (phba); |
@@ -1008,18 +1032,31 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
1008 | lpfc_cmd->pCmd->device->hostdata = ndlp->rport->dd_data; | 1032 | lpfc_cmd->pCmd->device->hostdata = ndlp->rport->dd_data; |
1009 | ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba); | 1033 | ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba); |
1010 | if (ret != SUCCESS) { | 1034 | if (ret != SUCCESS) { |
1011 | lpfc_printf_log(phba, KERN_INFO, LOG_FCP, | 1035 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
1012 | "%d:0713 Bus Reset on target %d failed\n", | 1036 | "%d:0713 Bus Reset on target %d failed\n", |
1013 | phba->brd_no, i); | 1037 | phba->brd_no, i); |
1014 | err_count++; | 1038 | err_count++; |
1015 | } | 1039 | } |
1016 | } | 1040 | } |
1017 | 1041 | ||
1042 | if (err_count == 0) | ||
1043 | ret = SUCCESS; | ||
1044 | |||
1045 | lpfc_release_scsi_buf(phba, lpfc_cmd); | ||
1046 | |||
1047 | /* | ||
1048 | * All outstanding txcmplq I/Os should have been aborted by | ||
1049 | * the targets. Unfortunately, some targets do not abide by | ||
1050 | * this forcing the driver to double check. | ||
1051 | */ | ||
1018 | cmnd->device->id = midlayer_id; | 1052 | cmnd->device->id = midlayer_id; |
1053 | cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | ||
1054 | 0, 0, LPFC_CTX_HOST); | ||
1055 | if (cnt) | ||
1056 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | ||
1057 | 0, 0, 0, LPFC_CTX_HOST); | ||
1019 | loopcnt = 0; | 1058 | loopcnt = 0; |
1020 | while((cnt = lpfc_sli_sum_iocb(phba, | 1059 | while(cnt) { |
1021 | &phba->sli.ring[phba->sli.fcp_ring], | ||
1022 | 0, 0, LPFC_CTX_HOST))) { | ||
1023 | spin_unlock_irq(phba->host->host_lock); | 1060 | spin_unlock_irq(phba->host->host_lock); |
1024 | schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); | 1061 | schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); |
1025 | spin_lock_irq(phba->host->host_lock); | 1062 | spin_lock_irq(phba->host->host_lock); |
@@ -1027,25 +1064,19 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
1027 | if (++loopcnt | 1064 | if (++loopcnt |
1028 | > (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT) | 1065 | > (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT) |
1029 | break; | 1066 | break; |
1067 | |||
1068 | cnt = lpfc_sli_sum_iocb(phba, | ||
1069 | &phba->sli.ring[phba->sli.fcp_ring], | ||
1070 | 0, 0, LPFC_CTX_HOST); | ||
1030 | } | 1071 | } |
1031 | 1072 | ||
1032 | if (cnt) { | 1073 | if (cnt) { |
1033 | /* flush all outstanding commands on the host */ | 1074 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
1034 | i = lpfc_sli_abort_iocb(phba, | ||
1035 | &phba->sli.ring[phba->sli.fcp_ring], 0, 0, 0, | ||
1036 | LPFC_CTX_HOST); | ||
1037 | |||
1038 | lpfc_printf_log(phba, KERN_INFO, LOG_FCP, | ||
1039 | "%d:0715 Bus Reset I/O flush failure: cnt x%x left x%x\n", | 1075 | "%d:0715 Bus Reset I/O flush failure: cnt x%x left x%x\n", |
1040 | phba->brd_no, cnt, i); | 1076 | phba->brd_no, cnt, i); |
1041 | } | ||
1042 | |||
1043 | if (cnt == 0) | ||
1044 | ret = SUCCESS; | ||
1045 | else | ||
1046 | ret = FAILED; | 1077 | ret = FAILED; |
1078 | } | ||
1047 | 1079 | ||
1048 | lpfc_release_scsi_buf(phba, lpfc_cmd); | ||
1049 | lpfc_printf_log(phba, | 1080 | lpfc_printf_log(phba, |
1050 | KERN_ERR, | 1081 | KERN_ERR, |
1051 | LOG_FCP, | 1082 | LOG_FCP, |
@@ -1053,6 +1084,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
1053 | phba->brd_no, ret); | 1084 | phba->brd_no, ret); |
1054 | out: | 1085 | out: |
1055 | spin_unlock_irq(shost->host_lock); | 1086 | spin_unlock_irq(shost->host_lock); |
1087 | lpfc_unblock_requests(phba); | ||
1056 | return ret; | 1088 | return ret; |
1057 | } | 1089 | } |
1058 | 1090 | ||