aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message
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
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')
-rw-r--r--drivers/message/fusion/mptbase.c63
-rw-r--r--drivers/message/fusion/mptbase.h66
-rw-r--r--drivers/message/fusion/mptsas.c2
-rw-r--r--drivers/message/fusion/mptscsih.c3
-rw-r--r--drivers/message/fusion/mptscsih.h1
5 files changed, 105 insertions, 30 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",
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index fe902338539b..69ddabd51958 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -554,10 +554,47 @@ struct mptfc_rport_info
554 u8 flags; 554 u8 flags;
555}; 555};
556 556
557/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
558
559/*
560 * MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers
561 * Private to the driver.
562 */
563
564#define MPT_HOST_BUS_UNKNOWN (0xFF)
565#define MPT_HOST_TOO_MANY_TM (0x05)
566#define MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
567#define MPT_HOST_NO_CHAIN (0xFFFFFFFF)
568#define MPT_NVRAM_MASK_TIMEOUT (0x000000FF)
569#define MPT_NVRAM_SYNC_MASK (0x0000FF00)
570#define MPT_NVRAM_SYNC_SHIFT (8)
571#define MPT_NVRAM_DISCONNECT_ENABLE (0x00010000)
572#define MPT_NVRAM_ID_SCAN_ENABLE (0x00020000)
573#define MPT_NVRAM_LUN_SCAN_ENABLE (0x00040000)
574#define MPT_NVRAM_TAG_QUEUE_ENABLE (0x00080000)
575#define MPT_NVRAM_WIDE_DISABLE (0x00100000)
576#define MPT_NVRAM_BOOT_CHOICE (0x00200000)
577
578typedef enum {
579 FC,
580 SPI,
581 SAS
582} BUS_TYPE;
583
584typedef struct _MPT_SCSI_HOST {
585 struct _MPT_ADAPTER *ioc;
586 ushort sel_timeout[MPT_MAX_FC_DEVICES];
587 char *info_kbuf;
588 long last_queue_full;
589 u16 spi_pending;
590 struct list_head target_reset_list;
591} MPT_SCSI_HOST;
592
557typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr); 593typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr);
558typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length, 594typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length,
559 dma_addr_t dma_addr); 595 dma_addr_t dma_addr);
560typedef void (*MPT_SCHEDULE_TARGET_RESET)(void *ioc); 596typedef void (*MPT_SCHEDULE_TARGET_RESET)(void *ioc);
597typedef void (*MPT_FLUSH_RUNNING_CMDS)(MPT_SCSI_HOST *hd);
561 598
562/* 599/*
563 * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS 600 * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
@@ -717,6 +754,7 @@ typedef struct _MPT_ADAPTER
717 u8 taskmgmt_quiesce_io; 754 u8 taskmgmt_quiesce_io;
718 u8 ioc_reset_in_progress; 755 u8 ioc_reset_in_progress;
719 MPT_SCHEDULE_TARGET_RESET schedule_target_reset; 756 MPT_SCHEDULE_TARGET_RESET schedule_target_reset;
757 MPT_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
720 struct work_struct sas_persist_task; 758 struct work_struct sas_persist_task;
721 759
722 struct work_struct fc_setup_reset_work; 760 struct work_struct fc_setup_reset_work;
@@ -830,19 +868,6 @@ typedef struct _MPT_LOCAL_REPLY {
830 u32 pad; 868 u32 pad;
831} MPT_LOCAL_REPLY; 869} MPT_LOCAL_REPLY;
832 870
833#define MPT_HOST_BUS_UNKNOWN (0xFF)
834#define MPT_HOST_TOO_MANY_TM (0x05)
835#define MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
836#define MPT_HOST_NO_CHAIN (0xFFFFFFFF)
837#define MPT_NVRAM_MASK_TIMEOUT (0x000000FF)
838#define MPT_NVRAM_SYNC_MASK (0x0000FF00)
839#define MPT_NVRAM_SYNC_SHIFT (8)
840#define MPT_NVRAM_DISCONNECT_ENABLE (0x00010000)
841#define MPT_NVRAM_ID_SCAN_ENABLE (0x00020000)
842#define MPT_NVRAM_LUN_SCAN_ENABLE (0x00040000)
843#define MPT_NVRAM_TAG_QUEUE_ENABLE (0x00080000)
844#define MPT_NVRAM_WIDE_DISABLE (0x00100000)
845#define MPT_NVRAM_BOOT_CHOICE (0x00200000)
846 871
847/* The TM_STATE variable is used to provide strict single threading of TM 872/* The TM_STATE variable is used to provide strict single threading of TM
848 * requests as well as communicate TM error conditions. 873 * requests as well as communicate TM error conditions.
@@ -851,21 +876,6 @@ typedef struct _MPT_LOCAL_REPLY {
851#define TM_STATE_IN_PROGRESS (1) 876#define TM_STATE_IN_PROGRESS (1)
852#define TM_STATE_ERROR (2) 877#define TM_STATE_ERROR (2)
853 878
854typedef enum {
855 FC,
856 SPI,
857 SAS
858} BUS_TYPE;
859
860typedef struct _MPT_SCSI_HOST {
861 MPT_ADAPTER *ioc;
862 ushort sel_timeout[MPT_MAX_FC_DEVICES];
863 char *info_kbuf;
864 long last_queue_full;
865 u16 spi_pending;
866 struct list_head target_reset_list;
867} MPT_SCSI_HOST;
868
869/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 879/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
870/* 880/*
871 * More Dynamic Multi-Pathing stuff... 881 * More Dynamic Multi-Pathing stuff...
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 73229ff9cafa..d21924ba4b1a 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -5147,6 +5147,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
5147 ioc->TaskCtx = mptsasTaskCtx; 5147 ioc->TaskCtx = mptsasTaskCtx;
5148 ioc->InternalCtx = mptsasInternalCtx; 5148 ioc->InternalCtx = mptsasInternalCtx;
5149 ioc->schedule_target_reset = &mptsas_schedule_target_reset; 5149 ioc->schedule_target_reset = &mptsas_schedule_target_reset;
5150 ioc->schedule_dead_ioc_flush_running_cmds =
5151 &mptscsih_flush_running_cmds;
5150 /* Added sanity check on readiness of the MPT adapter. 5152 /* Added sanity check on readiness of the MPT adapter.
5151 */ 5153 */
5152 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { 5154 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index ce61a5769765..de8cf92d8614 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1024,7 +1024,7 @@ out:
1024 * 1024 *
1025 * Must be called while new I/Os are being queued. 1025 * Must be called while new I/Os are being queued.
1026 */ 1026 */
1027static void 1027void
1028mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) 1028mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
1029{ 1029{
1030 MPT_ADAPTER *ioc = hd->ioc; 1030 MPT_ADAPTER *ioc = hd->ioc;
@@ -1055,6 +1055,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
1055 sc->scsi_done(sc); 1055 sc->scsi_done(sc);
1056 } 1056 }
1057} 1057}
1058EXPORT_SYMBOL(mptscsih_flush_running_cmds);
1058 1059
1059/* 1060/*
1060 * mptscsih_search_running_cmds - Delete any commands associated 1061 * mptscsih_search_running_cmds - Delete any commands associated
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 45a5ff3eff61..43e75ff39921 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -135,3 +135,4 @@ extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
135extern struct device_attribute *mptscsih_host_attrs[]; 135extern struct device_attribute *mptscsih_host_attrs[];
136extern struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); 136extern struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
137extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); 137extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
138extern void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd);