aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptbase.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-01-09 02:38:23 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-01-09 02:38:23 -0500
commitda733563be5a9da26fe81d9f007262d00b846e22 (patch)
treedb28291df94a2043af2123911984c5c173da4e6f /drivers/message/fusion/mptbase.c
parent6ccbcf2cb41131f8d56ef0723bf3f7c1f8486076 (diff)
parentdab78d7924598ea4031663dd10db814e2e324928 (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r--drivers/message/fusion/mptbase.c92
1 files changed, 88 insertions, 4 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 7956a10f9488..e9c6a6047a00 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -63,6 +63,8 @@
63#ifdef CONFIG_MTRR 63#ifdef CONFIG_MTRR
64#include <asm/mtrr.h> 64#include <asm/mtrr.h>
65#endif 65#endif
66#include <linux/kthread.h>
67#include <scsi/scsi_host.h>
66 68
67#include "mptbase.h" 69#include "mptbase.h"
68#include "lsi/mpi_log_fc.h" 70#include "lsi/mpi_log_fc.h"
@@ -323,6 +325,32 @@ mpt_is_discovery_complete(MPT_ADAPTER *ioc)
323 return rc; 325 return rc;
324} 326}
325 327
328
329/**
330 * mpt_remove_dead_ioc_func - kthread context to remove dead ioc
331 * @arg: input argument, used to derive ioc
332 *
333 * Return 0 if controller is removed from pci subsystem.
334 * Return -1 for other case.
335 */
336static int mpt_remove_dead_ioc_func(void *arg)
337{
338 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
339 struct pci_dev *pdev;
340
341 if ((ioc == NULL))
342 return -1;
343
344 pdev = ioc->pcidev;
345 if ((pdev == NULL))
346 return -1;
347
348 pci_remove_bus_device(pdev);
349 return 0;
350}
351
352
353
326/** 354/**
327 * mpt_fault_reset_work - work performed on workq after ioc fault 355 * mpt_fault_reset_work - work performed on workq after ioc fault
328 * @work: input argument, used to derive ioc 356 * @work: input argument, used to derive ioc
@@ -336,12 +364,45 @@ mpt_fault_reset_work(struct work_struct *work)
336 u32 ioc_raw_state; 364 u32 ioc_raw_state;
337 int rc; 365 int rc;
338 unsigned long flags; 366 unsigned long flags;
367 MPT_SCSI_HOST *hd;
368 struct task_struct *p;
339 369
340 if (ioc->ioc_reset_in_progress || !ioc->active) 370 if (ioc->ioc_reset_in_progress || !ioc->active)
341 goto out; 371 goto out;
342 372
373
343 ioc_raw_state = mpt_GetIocState(ioc, 0); 374 ioc_raw_state = mpt_GetIocState(ioc, 0);
344 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) { 375 if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_MASK) {
376 printk(MYIOC_s_INFO_FMT "%s: IOC is non-operational !!!!\n",
377 ioc->name, __func__);
378
379 /*
380 * Call mptscsih_flush_pending_cmds callback so that we
381 * flush all pending commands back to OS.
382 * This call is required to aovid deadlock at block layer.
383 * Dead IOC will fail to do diag reset,and this call is safe
384 * since dead ioc will never return any command back from HW.
385 */
386 hd = shost_priv(ioc->sh);
387 ioc->schedule_dead_ioc_flush_running_cmds(hd);
388
389 /*Remove the Dead Host */
390 p = kthread_run(mpt_remove_dead_ioc_func, ioc,
391 "mpt_dead_ioc_%d", ioc->id);
392 if (IS_ERR(p)) {
393 printk(MYIOC_s_ERR_FMT
394 "%s: Running mpt_dead_ioc thread failed !\n",
395 ioc->name, __func__);
396 } else {
397 printk(MYIOC_s_WARN_FMT
398 "%s: Running mpt_dead_ioc thread success !\n",
399 ioc->name, __func__);
400 }
401 return; /* don't rearm timer */
402 }
403
404 if ((ioc_raw_state & MPI_IOC_STATE_MASK)
405 == MPI_IOC_STATE_FAULT) {
345 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n", 406 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
346 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK); 407 ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
347 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n", 408 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
@@ -6413,8 +6474,19 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
6413 pReq->Action, ioc->mptbase_cmds.status, timeleft)); 6474 pReq->Action, ioc->mptbase_cmds.status, timeleft));
6414 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) 6475 if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
6415 goto out; 6476 goto out;
6416 if (!timeleft) 6477 if (!timeleft) {
6478 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6479 if (ioc->ioc_reset_in_progress) {
6480 spin_unlock_irqrestore(&ioc->taskmgmt_lock,
6481 flags);
6482 printk(MYIOC_s_INFO_FMT "%s: host reset in"
6483 " progress mpt_config timed out.!!\n",
6484 __func__, ioc->name);
6485 return -EFAULT;
6486 }
6487 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6417 issue_hard_reset = 1; 6488 issue_hard_reset = 1;
6489 }
6418 goto out; 6490 goto out;
6419 } 6491 }
6420 6492
@@ -7128,7 +7200,18 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
7128 spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 7200 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7129 if (ioc->ioc_reset_in_progress) { 7201 if (ioc->ioc_reset_in_progress) {
7130 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 7202 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7131 return 0; 7203 ioc->wait_on_reset_completion = 1;
7204 do {
7205 ssleep(1);
7206 } while (ioc->ioc_reset_in_progress == 1);
7207 ioc->wait_on_reset_completion = 0;
7208 return ioc->reset_status;
7209 }
7210 if (ioc->wait_on_reset_completion) {
7211 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7212 rc = 0;
7213 time_count = jiffies;
7214 goto exit;
7132 } 7215 }
7133 ioc->ioc_reset_in_progress = 1; 7216 ioc->ioc_reset_in_progress = 1;
7134 if (ioc->alt_ioc) 7217 if (ioc->alt_ioc)
@@ -7165,6 +7248,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
7165 ioc->ioc_reset_in_progress = 0; 7248 ioc->ioc_reset_in_progress = 0;
7166 ioc->taskmgmt_quiesce_io = 0; 7249 ioc->taskmgmt_quiesce_io = 0;
7167 ioc->taskmgmt_in_progress = 0; 7250 ioc->taskmgmt_in_progress = 0;
7251 ioc->reset_status = rc;
7168 if (ioc->alt_ioc) { 7252 if (ioc->alt_ioc) {
7169 ioc->alt_ioc->ioc_reset_in_progress = 0; 7253 ioc->alt_ioc->ioc_reset_in_progress = 0;
7170 ioc->alt_ioc->taskmgmt_quiesce_io = 0; 7254 ioc->alt_ioc->taskmgmt_quiesce_io = 0;
@@ -7180,7 +7264,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
7180 ioc->alt_ioc, MPT_IOC_POST_RESET); 7264 ioc->alt_ioc, MPT_IOC_POST_RESET);
7181 } 7265 }
7182 } 7266 }
7183 7267exit:
7184 dtmprintk(ioc, 7268 dtmprintk(ioc,
7185 printk(MYIOC_s_DEBUG_FMT 7269 printk(MYIOC_s_DEBUG_FMT
7186 "HardResetHandler: completed (%d seconds): %s\n", ioc->name, 7270 "HardResetHandler: completed (%d seconds): %s\n", ioc->name,