diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 22:42:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 22:42:25 -0500 |
commit | 382f51fe2f2276344d8a21447656778cdf6583b6 (patch) | |
tree | c2836a2cca4126c9c026ce5aa2fdf9f1c8ccded6 /drivers/scsi/scsi_transport_fc.c | |
parent | 701791cc3c8fc6dd83f6ec8af7e2541b4a316606 (diff) | |
parent | 54987386ee3790f3900de4df2ed4deb0e18dfc9f (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (222 commits)
[SCSI] zfcp: Remove flag ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP
[SCSI] zfcp: Activate fc4s attributes for zfcp in FC transport class
[SCSI] zfcp: Block scsi_eh thread for rport state BLOCKED
[SCSI] zfcp: Update FSF error reporting
[SCSI] zfcp: Improve ELS ADISC handling
[SCSI] zfcp: Simplify handling of ct and els requests
[SCSI] zfcp: Remove ZFCP_DID_MASK
[SCSI] zfcp: Move WKA port to zfcp FC code
[SCSI] zfcp: Use common code definitions for FC CT structs
[SCSI] zfcp: Use common code definitions for FC ELS structs
[SCSI] zfcp: Update FCP protocol related code
[SCSI] zfcp: Dont fail SCSI commands when transitioning to blocked fc_rport
[SCSI] zfcp: Assign scheduled work to driver queue
[SCSI] zfcp: Remove STATUS_COMMON_REMOVE flag as it is not required anymore
[SCSI] zfcp: Implement module unloading
[SCSI] zfcp: Merge trace code for fsf requests in one function
[SCSI] zfcp: Access ports and units with container_of in sysfs code
[SCSI] zfcp: Remove suspend callback
[SCSI] zfcp: Remove global config_mutex
[SCSI] zfcp: Replace local reference counting with common kref
...
Diffstat (limited to 'drivers/scsi/scsi_transport_fc.c')
-rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 99 |
1 files changed, 71 insertions, 28 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index c6f70dae9b2e..6531c91501be 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> |
@@ -2384,6 +2385,7 @@ fc_rport_final_delete(struct work_struct *work) | |||
2384 | struct Scsi_Host *shost = rport_to_shost(rport); | 2385 | struct Scsi_Host *shost = rport_to_shost(rport); |
2385 | struct fc_internal *i = to_fc_internal(shost->transportt); | 2386 | struct fc_internal *i = to_fc_internal(shost->transportt); |
2386 | unsigned long flags; | 2387 | unsigned long flags; |
2388 | int do_callback = 0; | ||
2387 | 2389 | ||
2388 | /* | 2390 | /* |
2389 | * if a scan is pending, flush the SCSI Host work_q so that | 2391 | * if a scan is pending, flush the SCSI Host work_q so that |
@@ -2422,8 +2424,15 @@ fc_rport_final_delete(struct work_struct *work) | |||
2422 | * Avoid this call if we already called it when we preserved the | 2424 | * Avoid this call if we already called it when we preserved the |
2423 | * rport for the binding. | 2425 | * rport for the binding. |
2424 | */ | 2426 | */ |
2427 | spin_lock_irqsave(shost->host_lock, flags); | ||
2425 | if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) && | 2428 | if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) && |
2426 | (i->f->dev_loss_tmo_callbk)) | 2429 | (i->f->dev_loss_tmo_callbk)) { |
2430 | rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; | ||
2431 | do_callback = 1; | ||
2432 | } | ||
2433 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
2434 | |||
2435 | if (do_callback) | ||
2427 | i->f->dev_loss_tmo_callbk(rport); | 2436 | i->f->dev_loss_tmo_callbk(rport); |
2428 | 2437 | ||
2429 | fc_bsg_remove(rport->rqst_q); | 2438 | fc_bsg_remove(rport->rqst_q); |
@@ -2970,6 +2979,7 @@ fc_timeout_deleted_rport(struct work_struct *work) | |||
2970 | struct fc_internal *i = to_fc_internal(shost->transportt); | 2979 | struct fc_internal *i = to_fc_internal(shost->transportt); |
2971 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); | 2980 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); |
2972 | unsigned long flags; | 2981 | unsigned long flags; |
2982 | int do_callback = 0; | ||
2973 | 2983 | ||
2974 | spin_lock_irqsave(shost->host_lock, flags); | 2984 | spin_lock_irqsave(shost->host_lock, flags); |
2975 | 2985 | ||
@@ -3035,7 +3045,6 @@ fc_timeout_deleted_rport(struct work_struct *work) | |||
3035 | rport->roles = FC_PORT_ROLE_UNKNOWN; | 3045 | rport->roles = FC_PORT_ROLE_UNKNOWN; |
3036 | rport->port_state = FC_PORTSTATE_NOTPRESENT; | 3046 | rport->port_state = FC_PORTSTATE_NOTPRESENT; |
3037 | rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT; | 3047 | rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT; |
3038 | rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; | ||
3039 | 3048 | ||
3040 | /* | 3049 | /* |
3041 | * Pre-emptively kill I/O rather than waiting for the work queue | 3050 | * Pre-emptively kill I/O rather than waiting for the work queue |
@@ -3045,32 +3054,40 @@ fc_timeout_deleted_rport(struct work_struct *work) | |||
3045 | spin_unlock_irqrestore(shost->host_lock, flags); | 3054 | spin_unlock_irqrestore(shost->host_lock, flags); |
3046 | fc_terminate_rport_io(rport); | 3055 | fc_terminate_rport_io(rport); |
3047 | 3056 | ||
3048 | BUG_ON(rport->port_state != FC_PORTSTATE_NOTPRESENT); | 3057 | spin_lock_irqsave(shost->host_lock, flags); |
3058 | |||
3059 | if (rport->port_state == FC_PORTSTATE_NOTPRESENT) { /* still missing */ | ||
3049 | 3060 | ||
3050 | /* remove the identifiers that aren't used in the consisting binding */ | 3061 | /* remove the identifiers that aren't used in the consisting binding */ |
3051 | switch (fc_host->tgtid_bind_type) { | 3062 | switch (fc_host->tgtid_bind_type) { |
3052 | case FC_TGTID_BIND_BY_WWPN: | 3063 | case FC_TGTID_BIND_BY_WWPN: |
3053 | rport->node_name = -1; | 3064 | rport->node_name = -1; |
3054 | rport->port_id = -1; | 3065 | rport->port_id = -1; |
3055 | break; | 3066 | break; |
3056 | case FC_TGTID_BIND_BY_WWNN: | 3067 | case FC_TGTID_BIND_BY_WWNN: |
3057 | rport->port_name = -1; | 3068 | rport->port_name = -1; |
3058 | rport->port_id = -1; | 3069 | rport->port_id = -1; |
3059 | break; | 3070 | break; |
3060 | case FC_TGTID_BIND_BY_ID: | 3071 | case FC_TGTID_BIND_BY_ID: |
3061 | rport->node_name = -1; | 3072 | rport->node_name = -1; |
3062 | rport->port_name = -1; | 3073 | rport->port_name = -1; |
3063 | break; | 3074 | break; |
3064 | case FC_TGTID_BIND_NONE: /* to keep compiler happy */ | 3075 | case FC_TGTID_BIND_NONE: /* to keep compiler happy */ |
3065 | break; | 3076 | break; |
3077 | } | ||
3078 | |||
3079 | /* | ||
3080 | * As this only occurs if the remote port (scsi target) | ||
3081 | * went away and didn't come back - we'll remove | ||
3082 | * all attached scsi devices. | ||
3083 | */ | ||
3084 | rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; | ||
3085 | fc_queue_work(shost, &rport->stgt_delete_work); | ||
3086 | |||
3087 | do_callback = 1; | ||
3066 | } | 3088 | } |
3067 | 3089 | ||
3068 | /* | 3090 | 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 | 3091 | ||
3075 | /* | 3092 | /* |
3076 | * Notify the driver that the rport is now dead. The LLDD will | 3093 | * Notify the driver that the rport is now dead. The LLDD will |
@@ -3078,7 +3095,7 @@ fc_timeout_deleted_rport(struct work_struct *work) | |||
3078 | * | 3095 | * |
3079 | * Note: we set the CALLBK_DONE flag above to correspond | 3096 | * Note: we set the CALLBK_DONE flag above to correspond |
3080 | */ | 3097 | */ |
3081 | if (i->f->dev_loss_tmo_callbk) | 3098 | if (do_callback && i->f->dev_loss_tmo_callbk) |
3082 | i->f->dev_loss_tmo_callbk(rport); | 3099 | i->f->dev_loss_tmo_callbk(rport); |
3083 | } | 3100 | } |
3084 | 3101 | ||
@@ -3128,6 +3145,31 @@ fc_scsi_scan_rport(struct work_struct *work) | |||
3128 | spin_unlock_irqrestore(shost->host_lock, flags); | 3145 | spin_unlock_irqrestore(shost->host_lock, flags); |
3129 | } | 3146 | } |
3130 | 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); | ||
3131 | 3173 | ||
3132 | /** | 3174 | /** |
3133 | * fc_vport_setup - allocates and creates a FC virtual port. | 3175 | * fc_vport_setup - allocates and creates a FC virtual port. |
@@ -3769,8 +3811,9 @@ fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost, | |||
3769 | return; | 3811 | return; |
3770 | 3812 | ||
3771 | while (!blk_queue_plugged(q)) { | 3813 | while (!blk_queue_plugged(q)) { |
3772 | if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED)) | 3814 | if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED) && |
3773 | break; | 3815 | !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)) |
3816 | break; | ||
3774 | 3817 | ||
3775 | req = blk_fetch_request(q); | 3818 | req = blk_fetch_request(q); |
3776 | if (!req) | 3819 | if (!req) |