aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2009-08-20 03:50:54 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-09-05 10:34:21 -0400
commitcd4e12e8ad246ec5bc23ab04d0da0e6985025620 (patch)
treed70dec04648c16b4c04d20935207d38a6eceb6e4 /drivers
parent69cb48750b02034350bc78d8053647d7464cdde0 (diff)
[SCSI] mpt2sas : Rescan topology from Interrupt context instead of work thread
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c3
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h1
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c142
3 files changed, 57 insertions, 89 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 35a13867495e..cc5a8dae4ae1 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -3536,5 +3536,8 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
3536 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); 3536 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3537 ioc->ioc_reset_in_progress = 0; 3537 ioc->ioc_reset_in_progress = 0;
3538 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); 3538 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
3539
3540 if (!r)
3541 _base_reset_handler(ioc, MPT2_IOC_RUNNING);
3539 return r; 3542 return r;
3540} 3543}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index acdcff150a35..998a7b847b3d 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -119,6 +119,7 @@
119#define MPT2_IOC_PRE_RESET 1 /* prior to host reset */ 119#define MPT2_IOC_PRE_RESET 1 /* prior to host reset */
120#define MPT2_IOC_AFTER_RESET 2 /* just after host reset */ 120#define MPT2_IOC_AFTER_RESET 2 /* just after host reset */
121#define MPT2_IOC_DONE_RESET 3 /* links re-initialized */ 121#define MPT2_IOC_DONE_RESET 3 /* links re-initialized */
122#define MPT2_IOC_RUNNING 4 /* shost running */
122 123
123/* 124/*
124 * logging format 125 * logging format
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 2e9a4445596f..471c3b604596 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -103,7 +103,6 @@ struct sense_info {
103}; 103};
104 104
105 105
106#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
107/** 106/**
108 * struct fw_event_work - firmware event struct 107 * struct fw_event_work - firmware event struct
109 * @list: link list framework 108 * @list: link list framework
@@ -2405,27 +2404,6 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
2405} 2404}
2406 2405
2407/** 2406/**
2408 * _scsih_queue_rescan - queue a topology rescan from user context
2409 * @ioc: per adapter object
2410 *
2411 * Return nothing.
2412 */
2413static void
2414_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc)
2415{
2416 struct fw_event_work *fw_event;
2417
2418 if (ioc->wait_for_port_enable_to_complete)
2419 return;
2420 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2421 if (!fw_event)
2422 return;
2423 fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET;
2424 fw_event->ioc = ioc;
2425 _scsih_fw_event_add(ioc, fw_event);
2426}
2427
2428/**
2429 * _scsih_flush_running_cmds - completing outstanding commands. 2407 * _scsih_flush_running_cmds - completing outstanding commands.
2430 * @ioc: per adapter object 2408 * @ioc: per adapter object
2431 * 2409 *
@@ -2456,46 +2434,6 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
2456} 2434}
2457 2435
2458/** 2436/**
2459 * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
2460 * @ioc: per adapter object
2461 * @reset_phase: phase
2462 *
2463 * The handler for doing any required cleanup or initialization.
2464 *
2465 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
2466 * MPT2_IOC_DONE_RESET
2467 *
2468 * Return nothing.
2469 */
2470void
2471mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
2472{
2473 switch (reset_phase) {
2474 case MPT2_IOC_PRE_RESET:
2475 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2476 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
2477 _scsih_fw_event_off(ioc);
2478 break;
2479 case MPT2_IOC_AFTER_RESET:
2480 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2481 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
2482 if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
2483 ioc->tm_cmds.status |= MPT2_CMD_RESET;
2484 mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
2485 complete(&ioc->tm_cmds.done);
2486 }
2487 _scsih_fw_event_on(ioc);
2488 _scsih_flush_running_cmds(ioc);
2489 break;
2490 case MPT2_IOC_DONE_RESET:
2491 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2492 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
2493 _scsih_queue_rescan(ioc);
2494 break;
2495 }
2496}
2497
2498/**
2499 * _scsih_setup_eedp - setup MPI request for EEDP transfer 2437 * _scsih_setup_eedp - setup MPI request for EEDP transfer
2500 * @scmd: pointer to scsi command object 2438 * @scmd: pointer to scsi command object
2501 * @mpi_request: pointer to the SCSI_IO reqest message frame 2439 * @mpi_request: pointer to the SCSI_IO reqest message frame
@@ -5156,22 +5094,9 @@ static void
5156_scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc) 5094_scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
5157{ 5095{
5158 struct _sas_device *sas_device, *sas_device_next; 5096 struct _sas_device *sas_device, *sas_device_next;
5159 struct _sas_node *sas_expander, *sas_expander_next; 5097 struct _sas_node *sas_expander;
5160 struct _raid_device *raid_device, *raid_device_next; 5098 struct _raid_device *raid_device, *raid_device_next;
5161 unsigned long flags;
5162 5099
5163 _scsih_search_responding_sas_devices(ioc);
5164 _scsih_search_responding_raid_devices(ioc);
5165 _scsih_search_responding_expanders(ioc);
5166
5167 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
5168 ioc->shost_recovery = 0;
5169 if (ioc->shost->shost_state == SHOST_RECOVERY) {
5170 printk(MPT2SAS_INFO_FMT "putting controller into "
5171 "SHOST_RUNNING\n", ioc->name);
5172 scsi_host_set_state(ioc->shost, SHOST_RUNNING);
5173 }
5174 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
5175 5100
5176 list_for_each_entry_safe(sas_device, sas_device_next, 5101 list_for_each_entry_safe(sas_device, sas_device_next,
5177 &ioc->sas_device_list, list) { 5102 &ioc->sas_device_list, list) {
@@ -5207,16 +5132,63 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
5207 _scsih_raid_device_remove(ioc, raid_device); 5132 _scsih_raid_device_remove(ioc, raid_device);
5208 } 5133 }
5209 5134
5210 list_for_each_entry_safe(sas_expander, sas_expander_next, 5135 retry_expander_search:
5211 &ioc->sas_expander_list, list) { 5136 sas_expander = NULL;
5137 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
5212 if (sas_expander->responding) { 5138 if (sas_expander->responding) {
5213 sas_expander->responding = 0; 5139 sas_expander->responding = 0;
5214 continue; 5140 continue;
5215 } 5141 }
5216 printk("\tremoving expander: handle(0x%04x), "
5217 " sas_addr(0x%016llx)\n", sas_expander->handle,
5218 (unsigned long long)sas_expander->sas_address);
5219 _scsih_expander_remove(ioc, sas_expander->handle); 5142 _scsih_expander_remove(ioc, sas_expander->handle);
5143 goto retry_expander_search;
5144 }
5145}
5146
5147/**
5148 * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
5149 * @ioc: per adapter object
5150 * @reset_phase: phase
5151 *
5152 * The handler for doing any required cleanup or initialization.
5153 *
5154 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
5155 * MPT2_IOC_DONE_RESET
5156 *
5157 * Return nothing.
5158 */
5159void
5160mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
5161{
5162 switch (reset_phase) {
5163 case MPT2_IOC_PRE_RESET:
5164 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
5165 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
5166 _scsih_fw_event_off(ioc);
5167 break;
5168 case MPT2_IOC_AFTER_RESET:
5169 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
5170 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
5171 if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
5172 ioc->tm_cmds.status |= MPT2_CMD_RESET;
5173 mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
5174 complete(&ioc->tm_cmds.done);
5175 }
5176 _scsih_fw_event_on(ioc);
5177 _scsih_flush_running_cmds(ioc);
5178 break;
5179 case MPT2_IOC_DONE_RESET:
5180 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
5181 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
5182 _scsih_sas_host_refresh(ioc, 0);
5183 _scsih_search_responding_sas_devices(ioc);
5184 _scsih_search_responding_raid_devices(ioc);
5185 _scsih_search_responding_expanders(ioc);
5186 break;
5187 case MPT2_IOC_RUNNING:
5188 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
5189 "MPT2_IOC_RUNNING\n", ioc->name, __func__));
5190 _scsih_remove_unresponding_devices(ioc);
5191 break;
5220 } 5192 }
5221} 5193}
5222 5194
@@ -5236,14 +5208,6 @@ _firmware_event_work(struct work_struct *work)
5236 unsigned long flags; 5208 unsigned long flags;
5237 struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; 5209 struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
5238 5210
5239 /* This is invoked by calling _scsih_queue_rescan(). */
5240 if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) {
5241 _scsih_fw_event_free(ioc, fw_event);
5242 _scsih_sas_host_refresh(ioc, 1);
5243 _scsih_remove_unresponding_devices(ioc);
5244 return;
5245 }
5246
5247 /* the queue is being flushed so ignore this event */ 5211 /* the queue is being flushed so ignore this event */
5248 spin_lock_irqsave(&ioc->fw_event_lock, flags); 5212 spin_lock_irqsave(&ioc->fw_event_lock, flags);
5249 if (ioc->fw_events_off || ioc->remove_host) { 5213 if (ioc->fw_events_off || ioc->remove_host) {