diff options
-rw-r--r-- | drivers/message/fusion/mptbase.c | 63 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 66 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 2 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 3 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.h | 1 |
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 | */ | ||
336 | static 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 | |||
578 | typedef enum { | ||
579 | FC, | ||
580 | SPI, | ||
581 | SAS | ||
582 | } BUS_TYPE; | ||
583 | |||
584 | typedef 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 | |||
557 | typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr); | 593 | typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr); |
558 | typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length, | 594 | typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length, |
559 | dma_addr_t dma_addr); | 595 | dma_addr_t dma_addr); |
560 | typedef void (*MPT_SCHEDULE_TARGET_RESET)(void *ioc); | 596 | typedef void (*MPT_SCHEDULE_TARGET_RESET)(void *ioc); |
597 | typedef 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 | ||
854 | typedef enum { | ||
855 | FC, | ||
856 | SPI, | ||
857 | SAS | ||
858 | } BUS_TYPE; | ||
859 | |||
860 | typedef 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 | */ |
1027 | static void | 1027 | void |
1028 | mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) | 1028 | mptscsih_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 | } |
1058 | EXPORT_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); | |||
135 | extern struct device_attribute *mptscsih_host_attrs[]; | 135 | extern struct device_attribute *mptscsih_host_attrs[]; |
136 | extern struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); | 136 | extern struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); |
137 | extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); | 137 | extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); |
138 | extern void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd); | ||