aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptbase.c
diff options
context:
space:
mode:
authorkashyap.desai@lsi.com <kashyap.desai@lsi.com>2011-08-04 07:12:15 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-27 10:35:16 -0400
commite62cca19a9bbfc72c62632d95a7c01cd6476708c (patch)
treead6f84c9423b950772669fc15de938e2be484387 /drivers/message/fusion/mptbase.c
parent3850b14e51d32fc0d4297ceb30f3f7bb2c2b4779 (diff)
[SCSI] mptfusion: Better handling of DEAD IOC PCI-E Link down error condition
Find Non-Operation IOC and remove it from OS: Detecting dead(non-functional) ioc will be done reading doorbell register value from fault reset thread, which has been called from work thread context after each specific interval. If doorbell value is 0xFFFFFFFF, it will be considered as IOC is non-operational and marked as dead ioc. Once Dead IOC has been detected, it will be removed at pci layer using "pci_remove_bus_device" API. Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r--drivers/message/fusion/mptbase.c63
1 files changed, 62 insertions, 1 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 7956a10f9488..517621fa8bca 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",