aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2009-09-23 07:56:58 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-10-29 13:03:10 -0400
commitfa7f31673583a6e0876f8bb420735cdd8a3ffa57 (patch)
tree5b547d903081571bc2cc5950de513beba4895ed0 /drivers/scsi/mpt2sas
parent9fec5f9fc2fbe7c6e39db01ae296528d9a20a5b1 (diff)
[SCSI] mpt2sas: Support for stopping driver when Firmware encounters
Added command line option and shost sysfs attribute called mpt2sas_fwfault_debug. When enduser writes a "1" to this parameter, this will enable support in the driver for debugging firmware timeout related issues. This handling was added in three areas (a) scsi error handling callback called task_abort, (b) IOCTL interface, and (c) other timeouts that result in diag resets, such as manufacturing config pages. When this support is enabled, the driver will provide dump_stack to console, halt controller firmware, and panic driver. The end user probably would want to setup serial console redirection so the dump stack can be seen. Here are the three methods for enable this support: (a) # insmod mpt2sas.ko mpt2sas_fwfault_debug=1 (b) # echo 1 > /sys/module/mpt2sas/parameters/mpt2sas_fwfault_debug (c) # echo 1 > /sys/class/scsi_host/host#/fwfault_debug (where # is the host number) Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: Eric Moore <Eric.moore@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/mpt2sas')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c88
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h4
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c41
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c2
4 files changed, 119 insertions, 16 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 670241efa4b5..617664cbf3f7 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -77,6 +77,32 @@ static int msix_disable = -1;
77module_param(msix_disable, int, 0); 77module_param(msix_disable, int, 0);
78MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); 78MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
79 79
80int mpt2sas_fwfault_debug;
81MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
82 "and halt firmware - (default=0)");
83
84/**
85 * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
86 *
87 */
88static int
89_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
90{
91 int ret = param_set_int(val, kp);
92 struct MPT2SAS_ADAPTER *ioc;
93
94 if (ret)
95 return ret;
96
97 printk(KERN_INFO "setting logging_level(0x%08x)\n",
98 mpt2sas_fwfault_debug);
99 list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
100 ioc->fwfault_debug = mpt2sas_fwfault_debug;
101 return 0;
102}
103module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug,
104 param_get_int, &mpt2sas_fwfault_debug, 0644);
105
80/** 106/**
81 * _base_fault_reset_work - workq handling ioc fault conditions 107 * _base_fault_reset_work - workq handling ioc fault conditions
82 * @work: input argument, used to derive ioc 108 * @work: input argument, used to derive ioc
@@ -177,6 +203,51 @@ mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
177 } 203 }
178} 204}
179 205
206/**
207 * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
208 * @ioc: per adapter object
209 * @fault_code: fault code
210 *
211 * Return nothing.
212 */
213void
214mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
215{
216 printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
217 ioc->name, fault_code);
218}
219
220/**
221 * mpt2sas_halt_firmware - halt's mpt controller firmware
222 * @ioc: per adapter object
223 *
224 * For debugging timeout related issues. Writing 0xCOFFEE00
225 * to the doorbell register will halt controller firmware. With
226 * the purpose to stop both driver and firmware, the enduser can
227 * obtain a ring buffer from controller UART.
228 */
229void
230mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc)
231{
232 u32 doorbell;
233
234 if (!ioc->fwfault_debug)
235 return;
236
237 dump_stack();
238
239 doorbell = readl(&ioc->chip->Doorbell);
240 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
241 mpt2sas_base_fault_info(ioc , doorbell);
242 else {
243 writel(0xC0FFEE00, &ioc->chip->Doorbell);
244 printk(MPT2SAS_ERR_FMT "Firmware is halted due to command "
245 "timeout\n", ioc->name);
246 }
247
248 panic("panic in %s\n", __func__);
249}
250
180#ifdef CONFIG_SCSI_MPT2SAS_LOGGING 251#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
181/** 252/**
182 * _base_sas_ioc_info - verbose translation of the ioc status 253 * _base_sas_ioc_info - verbose translation of the ioc status
@@ -526,20 +597,6 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
526} 597}
527 598
528/** 599/**
529 * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
530 * @ioc: pointer to scsi command object
531 * @fault_code: fault code
532 *
533 * Return nothing.
534 */
535void
536mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
537{
538 printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
539 ioc->name, fault_code);
540}
541
542/**
543 * _base_display_reply_info - 600 * _base_display_reply_info -
544 * @ioc: pointer to scsi command object 601 * @ioc: pointer to scsi command object
545 * @smid: system request message index 602 * @smid: system request message index
@@ -3684,6 +3741,9 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
3684 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, 3741 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
3685 __func__)); 3742 __func__));
3686 3743
3744 if (mpt2sas_fwfault_debug)
3745 mpt2sas_halt_firmware(ioc);
3746
3687 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); 3747 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3688 if (ioc->shost_recovery) { 3748 if (ioc->shost_recovery) {
3689 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); 3749 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index fa99ff204e46..0c75c0e137f7 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -466,6 +466,7 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
466 * @chip_phys: physical addrss prior to mapping 466 * @chip_phys: physical addrss prior to mapping
467 * @pio_chip: I/O mapped register space 467 * @pio_chip: I/O mapped register space
468 * @logging_level: see mpt2sas_debug.h 468 * @logging_level: see mpt2sas_debug.h
469 * @fwfault_debug: debuging FW timeouts
469 * @ir_firmware: IR firmware present 470 * @ir_firmware: IR firmware present
470 * @bars: bitmask of BAR's that must be configured 471 * @bars: bitmask of BAR's that must be configured
471 * @mask_interrupts: ignore interrupt 472 * @mask_interrupts: ignore interrupt
@@ -587,6 +588,7 @@ struct MPT2SAS_ADAPTER {
587 unsigned long chip_phys; 588 unsigned long chip_phys;
588 unsigned long pio_chip; 589 unsigned long pio_chip;
589 int logging_level; 590 int logging_level;
591 int fwfault_debug;
590 u8 ir_firmware; 592 u8 ir_firmware;
591 int bars; 593 int bars;
592 u8 mask_interrupts; 594 u8 mask_interrupts;
@@ -803,6 +805,8 @@ int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
803 Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request); 805 Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request);
804void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type); 806void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type);
805 807
808void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
809
806/* scsih shared API */ 810/* scsih shared API */
807u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, 811u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
808 u32 reply); 812 u32 reply);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 57d724633906..6901a6706ede 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -896,6 +896,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
896 printk(MPT2SAS_INFO_FMT "issue target reset: handle " 896 printk(MPT2SAS_INFO_FMT "issue target reset: handle "
897 "= (0x%04x)\n", ioc->name, 897 "= (0x%04x)\n", ioc->name,
898 mpi_request->FunctionDependent1); 898 mpi_request->FunctionDependent1);
899 mpt2sas_halt_firmware(ioc);
899 mutex_lock(&ioc->tm_cmds.mutex); 900 mutex_lock(&ioc->tm_cmds.mutex);
900 mpt2sas_scsih_issue_tm(ioc, 901 mpt2sas_scsih_issue_tm(ioc,
901 mpi_request->FunctionDependent1, 0, 902 mpi_request->FunctionDependent1, 0,
@@ -2474,6 +2475,43 @@ _ctl_logging_level_store(struct device *cdev, struct device_attribute *attr,
2474static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, 2475static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR,
2475 _ctl_logging_level_show, _ctl_logging_level_store); 2476 _ctl_logging_level_show, _ctl_logging_level_store);
2476 2477
2478/* device attributes */
2479/*
2480 * _ctl_fwfault_debug_show - show/store fwfault_debug
2481 * @cdev - pointer to embedded class device
2482 * @buf - the buffer returned
2483 *
2484 * mpt2sas_fwfault_debug is command line option
2485 * A sysfs 'read/write' shost attribute.
2486 */
2487static ssize_t
2488_ctl_fwfault_debug_show(struct device *cdev,
2489 struct device_attribute *attr, char *buf)
2490{
2491 struct Scsi_Host *shost = class_to_shost(cdev);
2492 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2493
2494 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug);
2495}
2496static ssize_t
2497_ctl_fwfault_debug_store(struct device *cdev,
2498 struct device_attribute *attr, const char *buf, size_t count)
2499{
2500 struct Scsi_Host *shost = class_to_shost(cdev);
2501 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2502 int val = 0;
2503
2504 if (sscanf(buf, "%d", &val) != 1)
2505 return -EINVAL;
2506
2507 ioc->fwfault_debug = val;
2508 printk(MPT2SAS_INFO_FMT "fwfault_debug=%d\n", ioc->name,
2509 ioc->fwfault_debug);
2510 return strlen(buf);
2511}
2512static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR,
2513 _ctl_fwfault_debug_show, _ctl_fwfault_debug_store);
2514
2477struct device_attribute *mpt2sas_host_attrs[] = { 2515struct device_attribute *mpt2sas_host_attrs[] = {
2478 &dev_attr_version_fw, 2516 &dev_attr_version_fw,
2479 &dev_attr_version_bios, 2517 &dev_attr_version_bios,
@@ -2487,13 +2525,12 @@ struct device_attribute *mpt2sas_host_attrs[] = {
2487 &dev_attr_io_delay, 2525 &dev_attr_io_delay,
2488 &dev_attr_device_delay, 2526 &dev_attr_device_delay,
2489 &dev_attr_logging_level, 2527 &dev_attr_logging_level,
2528 &dev_attr_fwfault_debug,
2490 &dev_attr_fw_queue_depth, 2529 &dev_attr_fw_queue_depth,
2491 &dev_attr_host_sas_address, 2530 &dev_attr_host_sas_address,
2492 NULL, 2531 NULL,
2493}; 2532};
2494 2533
2495/* device attributes */
2496
2497/** 2534/**
2498 * _ctl_device_sas_address_show - sas address 2535 * _ctl_device_sas_address_show - sas address
2499 * @cdev - pointer to embedded class device 2536 * @cdev - pointer to embedded class device
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 91d61154a46c..59ea821c2a3c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -1929,6 +1929,8 @@ _scsih_abort(struct scsi_cmnd *scmd)
1929 goto out; 1929 goto out;
1930 } 1930 }
1931 1931
1932 mpt2sas_halt_firmware(ioc);
1933
1932 mutex_lock(&ioc->tm_cmds.mutex); 1934 mutex_lock(&ioc->tm_cmds.mutex);
1933 handle = sas_device_priv_data->sas_target->handle; 1935 handle = sas_device_priv_data->sas_target->handle;
1934 mpt2sas_scsih_issue_tm(ioc, handle, sas_device_priv_data->lun, 1936 mpt2sas_scsih_issue_tm(ioc, handle, sas_device_priv_data->lun,