aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_fc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 22:42:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 22:42:25 -0500
commit382f51fe2f2276344d8a21447656778cdf6583b6 (patch)
treec2836a2cca4126c9c026ce5aa2fdf9f1c8ccded6 /drivers/scsi/scsi_transport_fc.c
parent701791cc3c8fc6dd83f6ec8af7e2541b4a316606 (diff)
parent54987386ee3790f3900de4df2ed4deb0e18dfc9f (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.c99
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 */
3158void 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}
3172EXPORT_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)