Commit 65d430fa99cbd0e88d09a3343f697c51fc8a7009
Committed by
James Bottomley
1 parent
03b147083a
Exists in
master
and in
7 other branches
[SCSI] scsi_transport_fc: Introduce helper function for blocking scsi_eh
Move the duplicated code from FC LLDs to SCSI FC transport class. Acked-by: James Smart <james.smart@emulex.com> Acked-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Acked-by: Abhijeet Joglekar <abjoglek@cisco.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Showing 5 changed files with 37 additions and 65 deletions Side-by-side Diff
drivers/scsi/fnic/fnic_scsi.c
... | ... | @@ -1225,22 +1225,6 @@ |
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 | 1229 | * This function is exported to SCSI for sending abort cmnds. |
1246 | 1230 | * A SCSI IO is represented by a io_req in the driver. |
... | ... | @@ -1260,7 +1244,7 @@ |
1260 | 1244 | DECLARE_COMPLETION_ONSTACK(tm_done); |
1261 | 1245 | |
1262 | 1246 | /* Wait for rport to unblock */ |
1263 | - fnic_block_error_handler(sc); | |
1247 | + fc_block_scsi_eh(sc); | |
1264 | 1248 | |
1265 | 1249 | /* Get local-port, check ready and link up */ |
1266 | 1250 | lp = shost_priv(sc->device->host); |
... | ... | @@ -1542,7 +1526,7 @@ |
1542 | 1526 | DECLARE_COMPLETION_ONSTACK(tm_done); |
1543 | 1527 | |
1544 | 1528 | /* Wait for rport to unblock */ |
1545 | - fnic_block_error_handler(sc); | |
1529 | + fc_block_scsi_eh(sc); | |
1546 | 1530 | |
1547 | 1531 | /* Get local-port, check ready and link up */ |
1548 | 1532 | lp = shost_priv(sc->device->host); |
drivers/scsi/lpfc/lpfc_scsi.c
... | ... | @@ -2917,28 +2917,6 @@ |
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 | 2920 | * lpfc_abort_handler - scsi_host_template eh_abort_handler entry point |
2943 | 2921 | * @cmnd: Pointer to scsi_cmnd data structure. |
2944 | 2922 | * |
... | ... | @@ -2961,7 +2939,7 @@ |
2961 | 2939 | int ret = SUCCESS; |
2962 | 2940 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); |
2963 | 2941 | |
2964 | - lpfc_block_error_handler(cmnd); | |
2942 | + fc_block_scsi_eh(cmnd); | |
2965 | 2943 | lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; |
2966 | 2944 | BUG_ON(!lpfc_cmd); |
2967 | 2945 | |
... | ... | @@ -3259,7 +3237,7 @@ |
3259 | 3237 | struct lpfc_scsi_event_header scsi_event; |
3260 | 3238 | int status; |
3261 | 3239 | |
3262 | - lpfc_block_error_handler(cmnd); | |
3240 | + fc_block_scsi_eh(cmnd); | |
3263 | 3241 | |
3264 | 3242 | status = lpfc_chk_tgt_mapped(vport, cmnd); |
3265 | 3243 | if (status == FAILED) { |
... | ... | @@ -3318,7 +3296,7 @@ |
3318 | 3296 | struct lpfc_scsi_event_header scsi_event; |
3319 | 3297 | int status; |
3320 | 3298 | |
3321 | - lpfc_block_error_handler(cmnd); | |
3299 | + fc_block_scsi_eh(cmnd); | |
3322 | 3300 | |
3323 | 3301 | status = lpfc_chk_tgt_mapped(vport, cmnd); |
3324 | 3302 | if (status == FAILED) { |
... | ... | @@ -3384,7 +3362,7 @@ |
3384 | 3362 | fc_host_post_vendor_event(shost, fc_get_event_number(), |
3385 | 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 | 3368 | * Since the driver manages a single bus device, reset all |
drivers/scsi/qla2xxx/qla_os.c
... | ... | @@ -728,23 +728,6 @@ |
728 | 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 | 732 | * qla2xxx_eh_abort |
750 | 733 | * |
... | ... | @@ -774,7 +757,7 @@ |
774 | 757 | struct req_que *req = vha->req; |
775 | 758 | srb_t *spt; |
776 | 759 | |
777 | - qla2x00_block_error_handler(cmd); | |
760 | + fc_block_scsi_eh(cmd); | |
778 | 761 | |
779 | 762 | if (!CMD_SP(cmd)) |
780 | 763 | return SUCCESS; |
... | ... | @@ -905,7 +888,7 @@ |
905 | 888 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
906 | 889 | int err; |
907 | 890 | |
908 | - qla2x00_block_error_handler(cmd); | |
891 | + fc_block_scsi_eh(cmd); | |
909 | 892 | |
910 | 893 | if (!fcport) |
911 | 894 | return FAILED; |
... | ... | @@ -985,7 +968,7 @@ |
985 | 968 | unsigned long serial; |
986 | 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 | 973 | id = cmd->device->id; |
991 | 974 | lun = cmd->device->lun; |
... | ... | @@ -1048,7 +1031,7 @@ |
1048 | 1031 | srb_t *sp = (srb_t *) CMD_SP(cmd); |
1049 | 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 | 1036 | id = cmd->device->id; |
1054 | 1037 | lun = cmd->device->lun; |
drivers/scsi/scsi_transport_fc.c
... | ... | @@ -27,6 +27,7 @@ |
27 | 27 | */ |
28 | 28 | #include <linux/module.h> |
29 | 29 | #include <linux/init.h> |
30 | +#include <linux/delay.h> | |
30 | 31 | #include <scsi/scsi_device.h> |
31 | 32 | #include <scsi/scsi_host.h> |
32 | 33 | #include <scsi/scsi_transport.h> |
... | ... | @@ -3144,6 +3145,31 @@ |
3144 | 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 | 3175 | * fc_vport_setup - allocates and creates a FC virtual port. |
include/scsi/scsi_transport_fc.h
... | ... | @@ -807,6 +807,7 @@ |
807 | 807 | struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, |
808 | 808 | struct fc_vport_identifiers *); |
809 | 809 | int fc_vport_terminate(struct fc_vport *vport); |
810 | +void fc_block_scsi_eh(struct scsi_cmnd *cmnd); | |
810 | 811 | |
811 | 812 | #endif /* SCSI_TRANSPORT_FC_H */ |