aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas/mpt2sas_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c152
1 files changed, 122 insertions, 30 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 670241efa4b5..6422e258fd52 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -57,6 +57,7 @@
57#include <linux/dma-mapping.h> 57#include <linux/dma-mapping.h>
58#include <linux/sort.h> 58#include <linux/sort.h>
59#include <linux/io.h> 59#include <linux/io.h>
60#include <linux/time.h>
60 61
61#include "mpt2sas_base.h" 62#include "mpt2sas_base.h"
62 63
@@ -77,6 +78,44 @@ static int msix_disable = -1;
77module_param(msix_disable, int, 0); 78module_param(msix_disable, int, 0);
78MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); 79MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
79 80
81/* diag_buffer_enable is bitwise
82 * bit 0 set = TRACE
83 * bit 1 set = SNAPSHOT
84 * bit 2 set = EXTENDED
85 *
86 * Either bit can be set, or both
87 */
88static int diag_buffer_enable;
89module_param(diag_buffer_enable, int, 0);
90MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
91 "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
92
93int mpt2sas_fwfault_debug;
94MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
95 "and halt firmware - (default=0)");
96
97/**
98 * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
99 *
100 */
101static int
102_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
103{
104 int ret = param_set_int(val, kp);
105 struct MPT2SAS_ADAPTER *ioc;
106
107 if (ret)
108 return ret;
109
110 printk(KERN_INFO "setting logging_level(0x%08x)\n",
111 mpt2sas_fwfault_debug);
112 list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
113 ioc->fwfault_debug = mpt2sas_fwfault_debug;
114 return 0;
115}
116module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug,
117 param_get_int, &mpt2sas_fwfault_debug, 0644);
118
80/** 119/**
81 * _base_fault_reset_work - workq handling ioc fault conditions 120 * _base_fault_reset_work - workq handling ioc fault conditions
82 * @work: input argument, used to derive ioc 121 * @work: input argument, used to derive ioc
@@ -121,7 +160,7 @@ _base_fault_reset_work(struct work_struct *work)
121 160
122/** 161/**
123 * mpt2sas_base_start_watchdog - start the fault_reset_work_q 162 * mpt2sas_base_start_watchdog - start the fault_reset_work_q
124 * @ioc: pointer to scsi command object 163 * @ioc: per adapter object
125 * Context: sleep. 164 * Context: sleep.
126 * 165 *
127 * Return nothing. 166 * Return nothing.
@@ -155,7 +194,7 @@ mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
155 194
156/** 195/**
157 * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q 196 * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
158 * @ioc: pointer to scsi command object 197 * @ioc: per adapter object
159 * Context: sleep. 198 * Context: sleep.
160 * 199 *
161 * Return nothing. 200 * Return nothing.
@@ -177,10 +216,55 @@ mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
177 } 216 }
178} 217}
179 218
219/**
220 * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
221 * @ioc: per adapter object
222 * @fault_code: fault code
223 *
224 * Return nothing.
225 */
226void
227mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
228{
229 printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
230 ioc->name, fault_code);
231}
232
233/**
234 * mpt2sas_halt_firmware - halt's mpt controller firmware
235 * @ioc: per adapter object
236 *
237 * For debugging timeout related issues. Writing 0xCOFFEE00
238 * to the doorbell register will halt controller firmware. With
239 * the purpose to stop both driver and firmware, the enduser can
240 * obtain a ring buffer from controller UART.
241 */
242void
243mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc)
244{
245 u32 doorbell;
246
247 if (!ioc->fwfault_debug)
248 return;
249
250 dump_stack();
251
252 doorbell = readl(&ioc->chip->Doorbell);
253 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
254 mpt2sas_base_fault_info(ioc , doorbell);
255 else {
256 writel(0xC0FFEE00, &ioc->chip->Doorbell);
257 printk(MPT2SAS_ERR_FMT "Firmware is halted due to command "
258 "timeout\n", ioc->name);
259 }
260
261 panic("panic in %s\n", __func__);
262}
263
180#ifdef CONFIG_SCSI_MPT2SAS_LOGGING 264#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
181/** 265/**
182 * _base_sas_ioc_info - verbose translation of the ioc status 266 * _base_sas_ioc_info - verbose translation of the ioc status
183 * @ioc: pointer to scsi command object 267 * @ioc: per adapter object
184 * @mpi_reply: reply mf payload returned from firmware 268 * @mpi_reply: reply mf payload returned from firmware
185 * @request_hdr: request mf 269 * @request_hdr: request mf
186 * 270 *
@@ -394,7 +478,7 @@ _base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
394 478
395/** 479/**
396 * _base_display_event_data - verbose translation of firmware asyn events 480 * _base_display_event_data - verbose translation of firmware asyn events
397 * @ioc: pointer to scsi command object 481 * @ioc: per adapter object
398 * @mpi_reply: reply mf payload returned from firmware 482 * @mpi_reply: reply mf payload returned from firmware
399 * 483 *
400 * Return nothing. 484 * Return nothing.
@@ -474,7 +558,7 @@ _base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
474 558
475/** 559/**
476 * _base_sas_log_info - verbose translation of firmware log info 560 * _base_sas_log_info - verbose translation of firmware log info
477 * @ioc: pointer to scsi command object 561 * @ioc: per adapter object
478 * @log_info: log info 562 * @log_info: log info
479 * 563 *
480 * Return nothing. 564 * Return nothing.
@@ -526,22 +610,8 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
526} 610}
527 611
528/** 612/**
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 - 613 * _base_display_reply_info -
544 * @ioc: pointer to scsi command object 614 * @ioc: per adapter object
545 * @smid: system request message index 615 * @smid: system request message index
546 * @msix_index: MSIX table index supplied by the OS 616 * @msix_index: MSIX table index supplied by the OS
547 * @reply: reply message frame(lower 32bit addr) 617 * @reply: reply message frame(lower 32bit addr)
@@ -570,7 +640,7 @@ _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
570 640
571/** 641/**
572 * mpt2sas_base_done - base internal command completion routine 642 * mpt2sas_base_done - base internal command completion routine
573 * @ioc: pointer to scsi command object 643 * @ioc: per adapter object
574 * @smid: system request message index 644 * @smid: system request message index
575 * @msix_index: MSIX table index supplied by the OS 645 * @msix_index: MSIX table index supplied by the OS
576 * @reply: reply message frame(lower 32bit addr) 646 * @reply: reply message frame(lower 32bit addr)
@@ -603,7 +673,7 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
603 673
604/** 674/**
605 * _base_async_event - main callback handler for firmware asyn events 675 * _base_async_event - main callback handler for firmware asyn events
606 * @ioc: pointer to scsi command object 676 * @ioc: per adapter object
607 * @msix_index: MSIX table index supplied by the OS 677 * @msix_index: MSIX table index supplied by the OS
608 * @reply: reply message frame(lower 32bit addr) 678 * @reply: reply message frame(lower 32bit addr)
609 * 679 *
@@ -684,7 +754,7 @@ _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
684 754
685/** 755/**
686 * _base_mask_interrupts - disable interrupts 756 * _base_mask_interrupts - disable interrupts
687 * @ioc: pointer to scsi command object 757 * @ioc: per adapter object
688 * 758 *
689 * Disabling ResetIRQ, Reply and Doorbell Interrupts 759 * Disabling ResetIRQ, Reply and Doorbell Interrupts
690 * 760 *
@@ -704,7 +774,7 @@ _base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc)
704 774
705/** 775/**
706 * _base_unmask_interrupts - enable interrupts 776 * _base_unmask_interrupts - enable interrupts
707 * @ioc: pointer to scsi command object 777 * @ioc: per adapter object
708 * 778 *
709 * Enabling only Reply Interrupts 779 * Enabling only Reply Interrupts
710 * 780 *
@@ -1258,12 +1328,13 @@ mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1258 * @ioc: per adapter object 1328 * @ioc: per adapter object
1259 * @smid: system request message index 1329 * @smid: system request message index
1260 * 1330 *
1261 * Returns phys pointer to sense buffer. 1331 * Returns phys pointer to the low 32bit address of the sense buffer.
1262 */ 1332 */
1263dma_addr_t 1333__le32
1264mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) 1334mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1265{ 1335{
1266 return ioc->sense_dma + ((smid - 1) * SCSI_SENSE_BUFFERSIZE); 1336 return cpu_to_le32(ioc->sense_dma +
1337 ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
1267} 1338}
1268 1339
1269/** 1340/**
@@ -1697,6 +1768,12 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
1697 } 1768 }
1698 1769
1699 if (ioc->facts.IOCCapabilities & 1770 if (ioc->facts.IOCCapabilities &
1771 MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
1772 printk(KERN_INFO "%sDiag Extended Buffer", i ? "," : "");
1773 i++;
1774 }
1775
1776 if (ioc->facts.IOCCapabilities &
1700 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) { 1777 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
1701 printk("%sTask Set Full", i ? "," : ""); 1778 printk("%sTask Set Full", i ? "," : "");
1702 i++; 1779 i++;
@@ -2871,6 +2948,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2871 Mpi2IOCInitRequest_t mpi_request; 2948 Mpi2IOCInitRequest_t mpi_request;
2872 Mpi2IOCInitReply_t mpi_reply; 2949 Mpi2IOCInitReply_t mpi_reply;
2873 int r; 2950 int r;
2951 struct timeval current_time;
2952 u16 ioc_status;
2874 2953
2875 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, 2954 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
2876 __func__)); 2955 __func__));
@@ -2921,6 +3000,13 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2921 cpu_to_le32(ioc->reply_post_free_dma); 3000 cpu_to_le32(ioc->reply_post_free_dma);
2922#endif 3001#endif
2923 3002
3003 /* This time stamp specifies number of milliseconds
3004 * since epoch ~ midnight January 1, 1970.
3005 */
3006 do_gettimeofday(&current_time);
3007 mpi_request.TimeStamp = (current_time.tv_sec * 1000) +
3008 (current_time.tv_usec >> 3);
3009
2924 if (ioc->logging_level & MPT_DEBUG_INIT) { 3010 if (ioc->logging_level & MPT_DEBUG_INIT) {
2925 u32 *mfp; 3011 u32 *mfp;
2926 int i; 3012 int i;
@@ -2943,7 +3029,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2943 return r; 3029 return r;
2944 } 3030 }
2945 3031
2946 if (mpi_reply.IOCStatus != MPI2_IOCSTATUS_SUCCESS || 3032 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
3033 if (ioc_status != MPI2_IOCSTATUS_SUCCESS ||
2947 mpi_reply.IOCLogInfo) { 3034 mpi_reply.IOCLogInfo) {
2948 printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__); 3035 printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__);
2949 r = -EIO; 3036 r = -EIO;
@@ -3461,11 +3548,11 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3461 return r; 3548 return r;
3462 3549
3463 pci_set_drvdata(ioc->pdev, ioc->shost); 3550 pci_set_drvdata(ioc->pdev, ioc->shost);
3464 r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); 3551 r = _base_get_ioc_facts(ioc, CAN_SLEEP);
3465 if (r) 3552 if (r)
3466 goto out_free_resources; 3553 goto out_free_resources;
3467 3554
3468 r = _base_get_ioc_facts(ioc, CAN_SLEEP); 3555 r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
3469 if (r) 3556 if (r)
3470 goto out_free_resources; 3557 goto out_free_resources;
3471 3558
@@ -3531,6 +3618,8 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3531 goto out_free_resources; 3618 goto out_free_resources;
3532 3619
3533 mpt2sas_base_start_watchdog(ioc); 3620 mpt2sas_base_start_watchdog(ioc);
3621 if (diag_buffer_enable != 0)
3622 mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
3534 return 0; 3623 return 0;
3535 3624
3536 out_free_resources: 3625 out_free_resources:
@@ -3684,6 +3773,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, 3773 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
3685 __func__)); 3774 __func__));
3686 3775
3776 if (mpt2sas_fwfault_debug)
3777 mpt2sas_halt_firmware(ioc);
3778
3687 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); 3779 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3688 if (ioc->shost_recovery) { 3780 if (ioc->shost_recovery) {
3689 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); 3781 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);