[SCSI] mpt2sas : Rescan topology from Interrupt context instead of work thread
authorKashyap, Desai <kashyap.desai@lsi.com>
Thu, 20 Aug 2009 07:50:54 +0000 (13:20 +0530)
committerJames Bottomley <James.Bottomley@suse.de>
Sat, 5 Sep 2009 14:34:21 +0000 (09:34 -0500)
Following host reset its possible that the controller firmware could
assign new handles for devices, as well as adding or deleting devices. There is
code in the driver that will rescan the topology folowing host reset; updating
device handles, and remove devices that are no longer responding. This patch
will improve the responsivness by moving this rescaning from the delayed hotplug
worker thread to immediately following the host reset.

Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Reviewed-by: Eric Moore <Eric.moore@lsi.com>
Cc: Stable Tree <stable@kernel.org>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.h
drivers/scsi/mpt2sas/mpt2sas_scsih.c

index 35a13867495ee3c5c0b2ddd6e72b7433887f5c11..cc5a8dae4ae1f69aab4b0dacff2e50b318d9d0da 100644 (file)
@@ -3536,5 +3536,8 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
        ioc->ioc_reset_in_progress = 0;
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+       if (!r)
+               _base_reset_handler(ioc, MPT2_IOC_RUNNING);
        return r;
 }
index acdcff150a35015d391ae80b8b3eeb8d6f14f5c1..998a7b847b3dd8ccda3fbc84849562bc7e677beb 100644 (file)
 #define MPT2_IOC_PRE_RESET             1 /* prior to host reset */
 #define MPT2_IOC_AFTER_RESET           2 /* just after host reset */
 #define MPT2_IOC_DONE_RESET            3 /* links re-initialized */
+#define MPT2_IOC_RUNNING               4 /* shost running */
 
 /*
  * logging format
index 2e9a4445596f4a8e5707d74fb770aceeaa7b908d..471c3b6045964fceef57c790adca3fc526f46b85 100644 (file)
@@ -103,7 +103,6 @@ struct sense_info {
 };
 
 
-#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
 /**
  * struct fw_event_work - firmware event struct
  * @list: link list framework
@@ -2404,27 +2403,6 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
 
-/**
- * _scsih_queue_rescan - queue a topology rescan from user context
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct fw_event_work *fw_event;
-
-       if (ioc->wait_for_port_enable_to_complete)
-               return;
-       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
-       if (!fw_event)
-               return;
-       fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET;
-       fw_event->ioc = ioc;
-       _scsih_fw_event_add(ioc, fw_event);
-}
-
 /**
  * _scsih_flush_running_cmds - completing outstanding commands.
  * @ioc: per adapter object
@@ -2455,46 +2433,6 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
            ioc->name, count));
 }
 
-/**
- * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
- * @ioc: per adapter object
- * @reset_phase: phase
- *
- * The handler for doing any required cleanup or initialization.
- *
- * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
- * MPT2_IOC_DONE_RESET
- *
- * Return nothing.
- */
-void
-mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
-{
-       switch (reset_phase) {
-       case MPT2_IOC_PRE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
-                   "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
-               _scsih_fw_event_off(ioc);
-               break;
-       case MPT2_IOC_AFTER_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
-                   "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
-               if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
-                       ioc->tm_cmds.status |= MPT2_CMD_RESET;
-                       mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
-                       complete(&ioc->tm_cmds.done);
-               }
-               _scsih_fw_event_on(ioc);
-               _scsih_flush_running_cmds(ioc);
-               break;
-       case MPT2_IOC_DONE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
-                   "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
-               _scsih_queue_rescan(ioc);
-               break;
-       }
-}
-
 /**
  * _scsih_setup_eedp - setup MPI request for EEDP transfer
  * @scmd: pointer to scsi command object
@@ -5156,22 +5094,9 @@ static void
 _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
 {
        struct _sas_device *sas_device, *sas_device_next;
-       struct _sas_node *sas_expander, *sas_expander_next;
+       struct _sas_node *sas_expander;
        struct _raid_device *raid_device, *raid_device_next;
-       unsigned long flags;
 
-       _scsih_search_responding_sas_devices(ioc);
-       _scsih_search_responding_raid_devices(ioc);
-       _scsih_search_responding_expanders(ioc);
-
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       ioc->shost_recovery = 0;
-       if (ioc->shost->shost_state == SHOST_RECOVERY) {
-               printk(MPT2SAS_INFO_FMT "putting controller into "
-                   "SHOST_RUNNING\n", ioc->name);
-               scsi_host_set_state(ioc->shost, SHOST_RUNNING);
-       }
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
        list_for_each_entry_safe(sas_device, sas_device_next,
            &ioc->sas_device_list, list) {
@@ -5207,16 +5132,63 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
                _scsih_raid_device_remove(ioc, raid_device);
        }
 
-       list_for_each_entry_safe(sas_expander, sas_expander_next,
-           &ioc->sas_expander_list, list) {
+ retry_expander_search:
+       sas_expander = NULL;
+       list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
                if (sas_expander->responding) {
                        sas_expander->responding = 0;
                        continue;
                }
-               printk("\tremoving expander: handle(0x%04x), "
-                   " sas_addr(0x%016llx)\n", sas_expander->handle,
-                   (unsigned long long)sas_expander->sas_address);
                _scsih_expander_remove(ioc, sas_expander->handle);
+               goto retry_expander_search;
+       }
+}
+
+/**
+ * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
+ * @ioc: per adapter object
+ * @reset_phase: phase
+ *
+ * The handler for doing any required cleanup or initialization.
+ *
+ * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
+ * MPT2_IOC_DONE_RESET
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
+{
+       switch (reset_phase) {
+       case MPT2_IOC_PRE_RESET:
+               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+                   "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
+               _scsih_fw_event_off(ioc);
+               break;
+       case MPT2_IOC_AFTER_RESET:
+               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+                   "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
+               if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
+                       ioc->tm_cmds.status |= MPT2_CMD_RESET;
+                       mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
+                       complete(&ioc->tm_cmds.done);
+               }
+               _scsih_fw_event_on(ioc);
+               _scsih_flush_running_cmds(ioc);
+               break;
+       case MPT2_IOC_DONE_RESET:
+               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+                   "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
+               _scsih_sas_host_refresh(ioc, 0);
+               _scsih_search_responding_sas_devices(ioc);
+               _scsih_search_responding_raid_devices(ioc);
+               _scsih_search_responding_expanders(ioc);
+               break;
+       case MPT2_IOC_RUNNING:
+               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+                   "MPT2_IOC_RUNNING\n", ioc->name, __func__));
+               _scsih_remove_unresponding_devices(ioc);
+               break;
        }
 }
 
@@ -5236,14 +5208,6 @@ _firmware_event_work(struct work_struct *work)
        unsigned long flags;
        struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
 
-       /* This is invoked by calling _scsih_queue_rescan(). */
-       if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) {
-               _scsih_fw_event_free(ioc, fw_event);
-               _scsih_sas_host_refresh(ioc, 1);
-               _scsih_remove_unresponding_devices(ioc);
-               return;
-       }
-
        /* the queue is being flushed so ignore this event */
        spin_lock_irqsave(&ioc->fw_event_lock, flags);
        if (ioc->fw_events_off || ioc->remove_host) {