aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,