diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index a67fed10598a..f436e033adaf 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -2384,6 +2384,7 @@ fc_rport_final_delete(struct work_struct *work) | |||
2384 | struct Scsi_Host *shost = rport_to_shost(rport); | 2384 | struct Scsi_Host *shost = rport_to_shost(rport); |
2385 | struct fc_internal *i = to_fc_internal(shost->transportt); | 2385 | struct fc_internal *i = to_fc_internal(shost->transportt); |
2386 | unsigned long flags; | 2386 | unsigned long flags; |
2387 | int do_callback = 0; | ||
2387 | 2388 | ||
2388 | /* | 2389 | /* |
2389 | * if a scan is pending, flush the SCSI Host work_q so that | 2390 | * if a scan is pending, flush the SCSI Host work_q so that |
@@ -2422,8 +2423,15 @@ fc_rport_final_delete(struct work_struct *work) | |||
2422 | * Avoid this call if we already called it when we preserved the | 2423 | * Avoid this call if we already called it when we preserved the |
2423 | * rport for the binding. | 2424 | * rport for the binding. |
2424 | */ | 2425 | */ |
2426 | spin_lock_irqsave(shost->host_lock, flags); | ||
2425 | if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) && | 2427 | if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) && |
2426 | (i->f->dev_loss_tmo_callbk)) | 2428 | (i->f->dev_loss_tmo_callbk)) { |
2429 | rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; | ||
2430 | do_callback = 1; | ||
2431 | } | ||
2432 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
2433 | |||
2434 | if (do_callback) | ||
2427 | i->f->dev_loss_tmo_callbk(rport); | 2435 | i->f->dev_loss_tmo_callbk(rport); |
2428 | 2436 | ||
2429 | fc_bsg_remove(rport->rqst_q); | 2437 | fc_bsg_remove(rport->rqst_q); |
@@ -2970,6 +2978,7 @@ fc_timeout_deleted_rport(struct work_struct *work) | |||
2970 | struct fc_internal *i = to_fc_internal(shost->transportt); | 2978 | struct fc_internal *i = to_fc_internal(shost->transportt); |
2971 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); | 2979 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); |
2972 | unsigned long flags; | 2980 | unsigned long flags; |
2981 | int do_callback = 0; | ||
2973 | 2982 | ||
2974 | spin_lock_irqsave(shost->host_lock, flags); | 2983 | spin_lock_irqsave(shost->host_lock, flags); |
2975 | 2984 | ||
@@ -3035,7 +3044,6 @@ fc_timeout_deleted_rport(struct work_struct *work) | |||
3035 | rport->roles = FC_PORT_ROLE_UNKNOWN; | 3044 | rport->roles = FC_PORT_ROLE_UNKNOWN; |
3036 | rport->port_state = FC_PORTSTATE_NOTPRESENT; | 3045 | rport->port_state = FC_PORTSTATE_NOTPRESENT; |
3037 | rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT; | 3046 | rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT; |
3038 | rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; | ||
3039 | 3047 | ||
3040 | /* | 3048 | /* |
3041 | * Pre-emptively kill I/O rather than waiting for the work queue | 3049 | * Pre-emptively kill I/O rather than waiting for the work queue |
@@ -3045,32 +3053,40 @@ fc_timeout_deleted_rport(struct work_struct *work) | |||
3045 | spin_unlock_irqrestore(shost->host_lock, flags); | 3053 | spin_unlock_irqrestore(shost->host_lock, flags); |
3046 | fc_terminate_rport_io(rport); | 3054 | fc_terminate_rport_io(rport); |
3047 | 3055 | ||
3048 | BUG_ON(rport->port_state != FC_PORTSTATE_NOTPRESENT); | 3056 | spin_lock_irqsave(shost->host_lock, flags); |
3049 | 3057 | ||
3050 | /* remove the identifiers that aren't used in the consisting binding */ | 3058 | if (rport->port_state == FC_PORTSTATE_NOTPRESENT) { /* still missing */ |
3051 | switch (fc_host->tgtid_bind_type) { | 3059 | |
3052 | case FC_TGTID_BIND_BY_WWPN: | 3060 | /* remove the identifiers that aren't used in the consisting binding */ |
3053 | rport->node_name = -1; | 3061 | switch (fc_host->tgtid_bind_type) { |
3054 | rport->port_id = -1; | 3062 | case FC_TGTID_BIND_BY_WWPN: |
3055 | break; | 3063 | rport->node_name = -1; |
3056 | case FC_TGTID_BIND_BY_WWNN: | 3064 | rport->port_id = -1; |
3057 | rport->port_name = -1; | 3065 | break; |
3058 | rport->port_id = -1; | 3066 | case FC_TGTID_BIND_BY_WWNN: |
3059 | break; | 3067 | rport->port_name = -1; |
3060 | case FC_TGTID_BIND_BY_ID: | 3068 | rport->port_id = -1; |
3061 | rport->node_name = -1; | 3069 | break; |
3062 | rport->port_name = -1; | 3070 | case FC_TGTID_BIND_BY_ID: |
3063 | break; | 3071 | rport->node_name = -1; |
3064 | case FC_TGTID_BIND_NONE: /* to keep compiler happy */ | 3072 | rport->port_name = -1; |
3065 | break; | 3073 | break; |
3074 | case FC_TGTID_BIND_NONE: /* to keep compiler happy */ | ||
3075 | break; | ||
3076 | } | ||
3077 | |||
3078 | /* | ||
3079 | * As this only occurs if the remote port (scsi target) | ||
3080 | * went away and didn't come back - we'll remove | ||
3081 | * all attached scsi devices. | ||
3082 | */ | ||
3083 | rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; | ||
3084 | fc_queue_work(shost, &rport->stgt_delete_work); | ||
3085 | |||
3086 | do_callback = 1; | ||
3066 | } | 3087 | } |
3067 | 3088 | ||
3068 | /* | 3089 | spin_unlock_irqrestore(shost->host_lock, flags); |
3069 | * As this only occurs if the remote port (scsi target) | ||
3070 | * went away and didn't come back - we'll remove | ||
3071 | * all attached scsi devices. | ||
3072 | */ | ||
3073 | fc_queue_work(shost, &rport->stgt_delete_work); | ||
3074 | 3090 | ||
3075 | /* | 3091 | /* |
3076 | * Notify the driver that the rport is now dead. The LLDD will | 3092 | * Notify the driver that the rport is now dead. The LLDD will |
@@ -3078,7 +3094,7 @@ fc_timeout_deleted_rport(struct work_struct *work) | |||
3078 | * | 3094 | * |
3079 | * Note: we set the CALLBK_DONE flag above to correspond | 3095 | * Note: we set the CALLBK_DONE flag above to correspond |
3080 | */ | 3096 | */ |
3081 | if (i->f->dev_loss_tmo_callbk) | 3097 | if (do_callback && i->f->dev_loss_tmo_callbk) |
3082 | i->f->dev_loss_tmo_callbk(rport); | 3098 | i->f->dev_loss_tmo_callbk(rport); |
3083 | } | 3099 | } |
3084 | 3100 | ||