[SCSI] fc transport: restore missing dev_loss_tmo callback to LLDD
James Smart [Mon, 5 Jan 2009 17:14:18 +0000 (12:14 -0500)]
When we reworked the transport for the rport lifetimes, in cases where the
rport was reused as a container for tgt id bindings, we inadvertantly
removed the callback to the driver indicating that dev_loss_tmo had fired.

This patch restores that functionality.

Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

drivers/scsi/scsi_transport_fc.c
include/scsi/scsi_transport_fc.h

index dcef787..5f77417 100644 (file)
@@ -2407,8 +2407,12 @@ fc_rport_final_delete(struct work_struct *work)
        /*
         * Notify the driver that the rport is now dead. The LLDD will
         * also guarantee that any communication to the rport is terminated
+        *
+        * Avoid this call if we already called it when we preserved the
+        * rport for the binding.
         */
-       if (i->f->dev_loss_tmo_callbk)
+       if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) &&
+           (i->f->dev_loss_tmo_callbk))
                i->f->dev_loss_tmo_callbk(rport);
 
        transport_remove_device(dev);
@@ -2647,7 +2651,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
                                spin_lock_irqsave(shost->host_lock, flags);
 
                                rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
-                                                 FC_RPORT_DEVLOSS_PENDING);
+                                                 FC_RPORT_DEVLOSS_PENDING |
+                                                 FC_RPORT_DEVLOSS_CALLBK_DONE);
 
                                /* if target, initiate a scan */
                                if (rport->scsi_target_id != -1) {
@@ -2944,6 +2949,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
        struct fc_rport *rport =
                container_of(work, struct fc_rport, dev_loss_work.work);
        struct Scsi_Host *shost = rport_to_shost(rport);
+       struct fc_internal *i = to_fc_internal(shost->transportt);
        struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
        unsigned long flags;
 
@@ -3011,6 +3017,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
        rport->roles = FC_PORT_ROLE_UNKNOWN;
        rport->port_state = FC_PORTSTATE_NOTPRESENT;
        rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;
+       rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE;
 
        /*
         * Pre-emptively kill I/O rather than waiting for the work queue
@@ -3046,8 +3053,18 @@ fc_timeout_deleted_rport(struct work_struct *work)
         * all attached scsi devices.
         */
        fc_queue_work(shost, &rport->stgt_delete_work);
+
+       /*
+        * Notify the driver that the rport is now dead. The LLDD will
+        * also guarantee that any communication to the rport is terminated
+        *
+        * Note: we set the CALLBK_DONE flag above to correspond
+        */
+       if (i->f->dev_loss_tmo_callbk)
+               i->f->dev_loss_tmo_callbk(rport);
 }
 
+
 /**
  * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a disconnected SCSI target.
  * @work:      rport to terminate io on.
index 6e04e6f..c9184f7 100644 (file)
@@ -358,6 +358,7 @@ struct fc_rport {   /* aka fc_starget_attrs */
 #define FC_RPORT_DEVLOSS_PENDING       0x01
 #define FC_RPORT_SCAN_PENDING          0x02
 #define FC_RPORT_FAST_FAIL_TIMEDOUT    0x04
+#define FC_RPORT_DEVLOSS_CALLBK_DONE   0x08
 
 #define        dev_to_rport(d)                         \
        container_of(d, struct fc_rport, dev)