diff options
| -rw-r--r-- | drivers/scsi/fnic/fnic_scsi.c | 20 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 30 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 25 | ||||
| -rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 26 | ||||
| -rw-r--r-- | include/scsi/scsi_transport_fc.h | 1 |
5 files changed, 37 insertions, 65 deletions
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index b5d17385939b..8d26d7a9f01b 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c | |||
| @@ -1225,22 +1225,6 @@ void fnic_terminate_rport_io(struct fc_rport *rport) | |||
| 1225 | 1225 | ||
| 1226 | } | 1226 | } |
| 1227 | 1227 | ||
| 1228 | static void fnic_block_error_handler(struct scsi_cmnd *sc) | ||
| 1229 | { | ||
| 1230 | struct Scsi_Host *shost = sc->device->host; | ||
| 1231 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); | ||
| 1232 | unsigned long flags; | ||
| 1233 | |||
| 1234 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 1235 | while (rport->port_state == FC_PORTSTATE_BLOCKED) { | ||
| 1236 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 1237 | msleep(1000); | ||
| 1238 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 1239 | } | ||
| 1240 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 1241 | |||
| 1242 | } | ||
| 1243 | |||
| 1244 | /* | 1228 | /* |
| 1245 | * This function is exported to SCSI for sending abort cmnds. | 1229 | * This function is exported to SCSI for sending abort cmnds. |
| 1246 | * A SCSI IO is represented by a io_req in the driver. | 1230 | * A SCSI IO is represented by a io_req in the driver. |
| @@ -1260,7 +1244,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) | |||
| 1260 | DECLARE_COMPLETION_ONSTACK(tm_done); | 1244 | DECLARE_COMPLETION_ONSTACK(tm_done); |
| 1261 | 1245 | ||
| 1262 | /* Wait for rport to unblock */ | 1246 | /* Wait for rport to unblock */ |
| 1263 | fnic_block_error_handler(sc); | 1247 | fc_block_scsi_eh(sc); |
| 1264 | 1248 | ||
| 1265 | /* Get local-port, check ready and link up */ | 1249 | /* Get local-port, check ready and link up */ |
| 1266 | lp = shost_priv(sc->device->host); | 1250 | lp = shost_priv(sc->device->host); |
| @@ -1542,7 +1526,7 @@ int fnic_device_reset(struct scsi_cmnd *sc) | |||
| 1542 | DECLARE_COMPLETION_ONSTACK(tm_done); | 1526 | DECLARE_COMPLETION_ONSTACK(tm_done); |
| 1543 | 1527 | ||
| 1544 | /* Wait for rport to unblock */ | 1528 | /* Wait for rport to unblock */ |
| 1545 | fnic_block_error_handler(sc); | 1529 | fc_block_scsi_eh(sc); |
| 1546 | 1530 | ||
| 1547 | /* Get local-port, check ready and link up */ | 1531 | /* Get local-port, check ready and link up */ |
| 1548 | lp = shost_priv(sc->device->host); | 1532 | lp = shost_priv(sc->device->host); |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c88f59f0ce30..e25179193a82 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
| @@ -2917,28 +2917,6 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
| 2917 | } | 2917 | } |
| 2918 | 2918 | ||
| 2919 | /** | 2919 | /** |
| 2920 | * lpfc_block_error_handler - Routine to block error handler | ||
| 2921 | * @cmnd: Pointer to scsi_cmnd data structure. | ||
| 2922 | * | ||
| 2923 | * This routine blocks execution till fc_rport state is not FC_PORSTAT_BLCOEKD. | ||
| 2924 | **/ | ||
| 2925 | static void | ||
| 2926 | lpfc_block_error_handler(struct scsi_cmnd *cmnd) | ||
| 2927 | { | ||
| 2928 | struct Scsi_Host *shost = cmnd->device->host; | ||
| 2929 | struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); | ||
| 2930 | |||
| 2931 | spin_lock_irq(shost->host_lock); | ||
| 2932 | while (rport->port_state == FC_PORTSTATE_BLOCKED) { | ||
| 2933 | spin_unlock_irq(shost->host_lock); | ||
| 2934 | msleep(1000); | ||
| 2935 | spin_lock_irq(shost->host_lock); | ||
| 2936 | } | ||
| 2937 | spin_unlock_irq(shost->host_lock); | ||
| 2938 | return; | ||
| 2939 | } | ||
| 2940 | |||
| 2941 | /** | ||
| 2942 | * lpfc_abort_handler - scsi_host_template eh_abort_handler entry point | 2920 | * lpfc_abort_handler - scsi_host_template eh_abort_handler entry point |
| 2943 | * @cmnd: Pointer to scsi_cmnd data structure. | 2921 | * @cmnd: Pointer to scsi_cmnd data structure. |
| 2944 | * | 2922 | * |
| @@ -2961,7 +2939,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
| 2961 | int ret = SUCCESS; | 2939 | int ret = SUCCESS; |
| 2962 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); | 2940 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); |
| 2963 | 2941 | ||
| 2964 | lpfc_block_error_handler(cmnd); | 2942 | fc_block_scsi_eh(cmnd); |
| 2965 | lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; | 2943 | lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; |
| 2966 | BUG_ON(!lpfc_cmd); | 2944 | BUG_ON(!lpfc_cmd); |
| 2967 | 2945 | ||
| @@ -3259,7 +3237,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) | |||
| 3259 | struct lpfc_scsi_event_header scsi_event; | 3237 | struct lpfc_scsi_event_header scsi_event; |
| 3260 | int status; | 3238 | int status; |
| 3261 | 3239 | ||
| 3262 | lpfc_block_error_handler(cmnd); | 3240 | fc_block_scsi_eh(cmnd); |
| 3263 | 3241 | ||
| 3264 | status = lpfc_chk_tgt_mapped(vport, cmnd); | 3242 | status = lpfc_chk_tgt_mapped(vport, cmnd); |
| 3265 | if (status == FAILED) { | 3243 | if (status == FAILED) { |
| @@ -3318,7 +3296,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) | |||
| 3318 | struct lpfc_scsi_event_header scsi_event; | 3296 | struct lpfc_scsi_event_header scsi_event; |
| 3319 | int status; | 3297 | int status; |
| 3320 | 3298 | ||
| 3321 | lpfc_block_error_handler(cmnd); | 3299 | fc_block_scsi_eh(cmnd); |
| 3322 | 3300 | ||
| 3323 | status = lpfc_chk_tgt_mapped(vport, cmnd); | 3301 | status = lpfc_chk_tgt_mapped(vport, cmnd); |
| 3324 | if (status == FAILED) { | 3302 | if (status == FAILED) { |
| @@ -3384,7 +3362,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) | |||
| 3384 | fc_host_post_vendor_event(shost, fc_get_event_number(), | 3362 | fc_host_post_vendor_event(shost, fc_get_event_number(), |
| 3385 | sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); | 3363 | sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); |
| 3386 | 3364 | ||
| 3387 | lpfc_block_error_handler(cmnd); | 3365 | fc_block_scsi_eh(cmnd); |
| 3388 | 3366 | ||
| 3389 | /* | 3367 | /* |
| 3390 | * Since the driver manages a single bus device, reset all | 3368 | * Since the driver manages a single bus device, reset all |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d69744a62fe4..41669357b186 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
| @@ -728,23 +728,6 @@ qla2x00_abort_fcport_cmds(fc_port_t *fcport) | |||
| 728 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 728 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 729 | } | 729 | } |
| 730 | 730 | ||
| 731 | static void | ||
| 732 | qla2x00_block_error_handler(struct scsi_cmnd *cmnd) | ||
| 733 | { | ||
| 734 | struct Scsi_Host *shost = cmnd->device->host; | ||
| 735 | struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); | ||
| 736 | unsigned long flags; | ||
| 737 | |||
| 738 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 739 | while (rport->port_state == FC_PORTSTATE_BLOCKED) { | ||
| 740 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 741 | msleep(1000); | ||
| 742 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 743 | } | ||
| 744 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 745 | return; | ||
| 746 | } | ||
| 747 | |||
| 748 | /************************************************************************** | 731 | /************************************************************************** |
| 749 | * qla2xxx_eh_abort | 732 | * qla2xxx_eh_abort |
| 750 | * | 733 | * |
| @@ -774,7 +757,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
| 774 | struct req_que *req = vha->req; | 757 | struct req_que *req = vha->req; |
| 775 | srb_t *spt; | 758 | srb_t *spt; |
| 776 | 759 | ||
| 777 | qla2x00_block_error_handler(cmd); | 760 | fc_block_scsi_eh(cmd); |
| 778 | 761 | ||
| 779 | if (!CMD_SP(cmd)) | 762 | if (!CMD_SP(cmd)) |
| 780 | return SUCCESS; | 763 | return SUCCESS; |
| @@ -905,7 +888,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, | |||
| 905 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 888 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
| 906 | int err; | 889 | int err; |
| 907 | 890 | ||
| 908 | qla2x00_block_error_handler(cmd); | 891 | fc_block_scsi_eh(cmd); |
| 909 | 892 | ||
| 910 | if (!fcport) | 893 | if (!fcport) |
| 911 | return FAILED; | 894 | return FAILED; |
| @@ -985,7 +968,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | |||
| 985 | unsigned long serial; | 968 | unsigned long serial; |
| 986 | srb_t *sp = (srb_t *) CMD_SP(cmd); | 969 | srb_t *sp = (srb_t *) CMD_SP(cmd); |
| 987 | 970 | ||
| 988 | qla2x00_block_error_handler(cmd); | 971 | fc_block_scsi_eh(cmd); |
| 989 | 972 | ||
| 990 | id = cmd->device->id; | 973 | id = cmd->device->id; |
| 991 | lun = cmd->device->lun; | 974 | lun = cmd->device->lun; |
| @@ -1048,7 +1031,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
| 1048 | srb_t *sp = (srb_t *) CMD_SP(cmd); | 1031 | srb_t *sp = (srb_t *) CMD_SP(cmd); |
| 1049 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | 1032 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); |
| 1050 | 1033 | ||
| 1051 | qla2x00_block_error_handler(cmd); | 1034 | fc_block_scsi_eh(cmd); |
| 1052 | 1035 | ||
| 1053 | id = cmd->device->id; | 1036 | id = cmd->device->id; |
| 1054 | lun = cmd->device->lun; | 1037 | lun = cmd->device->lun; |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index f436e033adaf..3ce56b3b2cd7 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | */ | 27 | */ |
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
| 30 | #include <linux/delay.h> | ||
| 30 | #include <scsi/scsi_device.h> | 31 | #include <scsi/scsi_device.h> |
| 31 | #include <scsi/scsi_host.h> | 32 | #include <scsi/scsi_host.h> |
| 32 | #include <scsi/scsi_transport.h> | 33 | #include <scsi/scsi_transport.h> |
| @@ -3144,6 +3145,31 @@ fc_scsi_scan_rport(struct work_struct *work) | |||
| 3144 | spin_unlock_irqrestore(shost->host_lock, flags); | 3145 | spin_unlock_irqrestore(shost->host_lock, flags); |
| 3145 | } | 3146 | } |
| 3146 | 3147 | ||
| 3148 | /** | ||
| 3149 | * fc_block_scsi_eh - Block SCSI eh thread for blocked fc_rport | ||
| 3150 | * @cmnd: SCSI command that scsi_eh is trying to recover | ||
| 3151 | * | ||
| 3152 | * This routine can be called from a FC LLD scsi_eh callback. It | ||
| 3153 | * blocks the scsi_eh thread until the fc_rport leaves the | ||
| 3154 | * FC_PORTSTATE_BLOCKED. This is necessary to avoid the scsi_eh | ||
| 3155 | * failing recovery actions for blocked rports which would lead to | ||
| 3156 | * offlined SCSI devices. | ||
| 3157 | */ | ||
| 3158 | void fc_block_scsi_eh(struct scsi_cmnd *cmnd) | ||
| 3159 | { | ||
| 3160 | struct Scsi_Host *shost = cmnd->device->host; | ||
| 3161 | struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); | ||
| 3162 | unsigned long flags; | ||
| 3163 | |||
| 3164 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 3165 | while (rport->port_state == FC_PORTSTATE_BLOCKED) { | ||
| 3166 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 3167 | msleep(1000); | ||
| 3168 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 3169 | } | ||
| 3170 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 3171 | } | ||
| 3172 | EXPORT_SYMBOL(fc_block_scsi_eh); | ||
| 3147 | 3173 | ||
| 3148 | /** | 3174 | /** |
| 3149 | * fc_vport_setup - allocates and creates a FC virtual port. | 3175 | * fc_vport_setup - allocates and creates a FC virtual port. |
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index fc50bd64aa4e..8e86a94faf06 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h | |||
| @@ -807,5 +807,6 @@ void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, | |||
| 807 | struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, | 807 | struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, |
| 808 | struct fc_vport_identifiers *); | 808 | struct fc_vport_identifiers *); |
| 809 | int fc_vport_terminate(struct fc_vport *vport); | 809 | int fc_vport_terminate(struct fc_vport *vport); |
| 810 | void fc_block_scsi_eh(struct scsi_cmnd *cmnd); | ||
| 810 | 811 | ||
| 811 | #endif /* SCSI_TRANSPORT_FC_H */ | 812 | #endif /* SCSI_TRANSPORT_FC_H */ |
