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.c171
1 files changed, 136 insertions, 35 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 670241efa4b5..88e6eebc3159 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,43 @@ 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 fwfault_debug(%d)\n", mpt2sas_fwfault_debug);
111 list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
112 ioc->fwfault_debug = mpt2sas_fwfault_debug;
113 return 0;
114}
115module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug,
116 param_get_int, &mpt2sas_fwfault_debug, 0644);
117
80/** 118/**
81 * _base_fault_reset_work - workq handling ioc fault conditions 119 * _base_fault_reset_work - workq handling ioc fault conditions
82 * @work: input argument, used to derive ioc 120 * @work: input argument, used to derive ioc
@@ -121,7 +159,7 @@ _base_fault_reset_work(struct work_struct *work)
121 159
122/** 160/**
123 * mpt2sas_base_start_watchdog - start the fault_reset_work_q 161 * mpt2sas_base_start_watchdog - start the fault_reset_work_q
124 * @ioc: pointer to scsi command object 162 * @ioc: per adapter object
125 * Context: sleep. 163 * Context: sleep.
126 * 164 *
127 * Return nothing. 165 * Return nothing.
@@ -155,7 +193,7 @@ mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
155 193
156/** 194/**
157 * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q 195 * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
158 * @ioc: pointer to scsi command object 196 * @ioc: per adapter object
159 * Context: sleep. 197 * Context: sleep.
160 * 198 *
161 * Return nothing. 199 * Return nothing.
@@ -177,10 +215,55 @@ mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
177 } 215 }
178} 216}
179 217
218/**
219 * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
220 * @ioc: per adapter object
221 * @fault_code: fault code
222 *
223 * Return nothing.
224 */
225void
226mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
227{
228 printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
229 ioc->name, fault_code);
230}
231
232/**
233 * mpt2sas_halt_firmware - halt's mpt controller firmware
234 * @ioc: per adapter object
235 *
236 * For debugging timeout related issues. Writing 0xCOFFEE00
237 * to the doorbell register will halt controller firmware. With
238 * the purpose to stop both driver and firmware, the enduser can
239 * obtain a ring buffer from controller UART.
240 */
241void
242mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc)
243{
244 u32 doorbell;
245
246 if (!ioc->fwfault_debug)
247 return;
248
249 dump_stack();
250
251 doorbell = readl(&ioc->chip->Doorbell);
252 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
253 mpt2sas_base_fault_info(ioc , doorbell);
254 else {
255 writel(0xC0FFEE00, &ioc->chip->Doorbell);
256 printk(MPT2SAS_ERR_FMT "Firmware is halted due to command "
257 "timeout\n", ioc->name);
258 }
259
260 panic("panic in %s\n", __func__);
261}
262
180#ifdef CONFIG_SCSI_MPT2SAS_LOGGING 263#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
181/** 264/**
182 * _base_sas_ioc_info - verbose translation of the ioc status 265 * _base_sas_ioc_info - verbose translation of the ioc status
183 * @ioc: pointer to scsi command object 266 * @ioc: per adapter object
184 * @mpi_reply: reply mf payload returned from firmware 267 * @mpi_reply: reply mf payload returned from firmware
185 * @request_hdr: request mf 268 * @request_hdr: request mf
186 * 269 *
@@ -394,7 +477,7 @@ _base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
394 477
395/** 478/**
396 * _base_display_event_data - verbose translation of firmware asyn events 479 * _base_display_event_data - verbose translation of firmware asyn events
397 * @ioc: pointer to scsi command object 480 * @ioc: per adapter object
398 * @mpi_reply: reply mf payload returned from firmware 481 * @mpi_reply: reply mf payload returned from firmware
399 * 482 *
400 * Return nothing. 483 * Return nothing.
@@ -474,7 +557,7 @@ _base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
474 557
475/** 558/**
476 * _base_sas_log_info - verbose translation of firmware log info 559 * _base_sas_log_info - verbose translation of firmware log info
477 * @ioc: pointer to scsi command object 560 * @ioc: per adapter object
478 * @log_info: log info 561 * @log_info: log info
479 * 562 *
480 * Return nothing. 563 * Return nothing.
@@ -526,22 +609,8 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
526} 609}
527 610
528/** 611/**
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 - 612 * _base_display_reply_info -
544 * @ioc: pointer to scsi command object 613 * @ioc: per adapter object
545 * @smid: system request message index 614 * @smid: system request message index
546 * @msix_index: MSIX table index supplied by the OS 615 * @msix_index: MSIX table index supplied by the OS
547 * @reply: reply message frame(lower 32bit addr) 616 * @reply: reply message frame(lower 32bit addr)
@@ -570,7 +639,7 @@ _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
570 639
571/** 640/**
572 * mpt2sas_base_done - base internal command completion routine 641 * mpt2sas_base_done - base internal command completion routine
573 * @ioc: pointer to scsi command object 642 * @ioc: per adapter object
574 * @smid: system request message index 643 * @smid: system request message index
575 * @msix_index: MSIX table index supplied by the OS 644 * @msix_index: MSIX table index supplied by the OS
576 * @reply: reply message frame(lower 32bit addr) 645 * @reply: reply message frame(lower 32bit addr)
@@ -603,7 +672,7 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
603 672
604/** 673/**
605 * _base_async_event - main callback handler for firmware asyn events 674 * _base_async_event - main callback handler for firmware asyn events
606 * @ioc: pointer to scsi command object 675 * @ioc: per adapter object
607 * @msix_index: MSIX table index supplied by the OS 676 * @msix_index: MSIX table index supplied by the OS
608 * @reply: reply message frame(lower 32bit addr) 677 * @reply: reply message frame(lower 32bit addr)
609 * 678 *
@@ -684,7 +753,7 @@ _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
684 753
685/** 754/**
686 * _base_mask_interrupts - disable interrupts 755 * _base_mask_interrupts - disable interrupts
687 * @ioc: pointer to scsi command object 756 * @ioc: per adapter object
688 * 757 *
689 * Disabling ResetIRQ, Reply and Doorbell Interrupts 758 * Disabling ResetIRQ, Reply and Doorbell Interrupts
690 * 759 *
@@ -704,7 +773,7 @@ _base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc)
704 773
705/** 774/**
706 * _base_unmask_interrupts - enable interrupts 775 * _base_unmask_interrupts - enable interrupts
707 * @ioc: pointer to scsi command object 776 * @ioc: per adapter object
708 * 777 *
709 * Enabling only Reply Interrupts 778 * Enabling only Reply Interrupts
710 * 779 *
@@ -1152,6 +1221,8 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
1152 u32 memap_sz; 1221 u32 memap_sz;
1153 u32 pio_sz; 1222 u32 pio_sz;
1154 int i, r = 0; 1223 int i, r = 0;
1224 u64 pio_chip = 0;
1225 u64 chip_phys = 0;
1155 1226
1156 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", 1227 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n",
1157 ioc->name, __func__)); 1228 ioc->name, __func__));
@@ -1185,12 +1256,13 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
1185 if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO) { 1256 if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO) {
1186 if (pio_sz) 1257 if (pio_sz)
1187 continue; 1258 continue;
1188 ioc->pio_chip = pci_resource_start(pdev, i); 1259 pio_chip = (u64)pci_resource_start(pdev, i);
1189 pio_sz = pci_resource_len(pdev, i); 1260 pio_sz = pci_resource_len(pdev, i);
1190 } else { 1261 } else {
1191 if (memap_sz) 1262 if (memap_sz)
1192 continue; 1263 continue;
1193 ioc->chip_phys = pci_resource_start(pdev, i); 1264 ioc->chip_phys = pci_resource_start(pdev, i);
1265 chip_phys = (u64)ioc->chip_phys;
1194 memap_sz = pci_resource_len(pdev, i); 1266 memap_sz = pci_resource_len(pdev, i);
1195 ioc->chip = ioremap(ioc->chip_phys, memap_sz); 1267 ioc->chip = ioremap(ioc->chip_phys, memap_sz);
1196 if (ioc->chip == NULL) { 1268 if (ioc->chip == NULL) {
@@ -1210,10 +1282,10 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
1210 printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n", 1282 printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
1211 ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : 1283 ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
1212 "IO-APIC enabled"), ioc->pci_irq); 1284 "IO-APIC enabled"), ioc->pci_irq);
1213 printk(MPT2SAS_INFO_FMT "iomem(0x%lx), mapped(0x%p), size(%d)\n", 1285 printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
1214 ioc->name, ioc->chip_phys, ioc->chip, memap_sz); 1286 ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
1215 printk(MPT2SAS_INFO_FMT "ioport(0x%lx), size(%d)\n", 1287 printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n",
1216 ioc->name, ioc->pio_chip, pio_sz); 1288 ioc->name, (unsigned long long)pio_chip, pio_sz);
1217 1289
1218 return 0; 1290 return 0;
1219 1291
@@ -1258,12 +1330,13 @@ mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1258 * @ioc: per adapter object 1330 * @ioc: per adapter object
1259 * @smid: system request message index 1331 * @smid: system request message index
1260 * 1332 *
1261 * Returns phys pointer to sense buffer. 1333 * Returns phys pointer to the low 32bit address of the sense buffer.
1262 */ 1334 */
1263dma_addr_t 1335__le32
1264mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) 1336mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1265{ 1337{
1266 return ioc->sense_dma + ((smid - 1) * SCSI_SENSE_BUFFERSIZE); 1338 return cpu_to_le32(ioc->sense_dma +
1339 ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
1267} 1340}
1268 1341
1269/** 1342/**
@@ -1697,6 +1770,12 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
1697 } 1770 }
1698 1771
1699 if (ioc->facts.IOCCapabilities & 1772 if (ioc->facts.IOCCapabilities &
1773 MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
1774 printk(KERN_INFO "%sDiag Extended Buffer", i ? "," : "");
1775 i++;
1776 }
1777
1778 if (ioc->facts.IOCCapabilities &
1700 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) { 1779 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
1701 printk("%sTask Set Full", i ? "," : ""); 1780 printk("%sTask Set Full", i ? "," : "");
1702 i++; 1781 i++;
@@ -2871,6 +2950,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2871 Mpi2IOCInitRequest_t mpi_request; 2950 Mpi2IOCInitRequest_t mpi_request;
2872 Mpi2IOCInitReply_t mpi_reply; 2951 Mpi2IOCInitReply_t mpi_reply;
2873 int r; 2952 int r;
2953 struct timeval current_time;
2954 u16 ioc_status;
2874 2955
2875 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, 2956 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
2876 __func__)); 2957 __func__));
@@ -2921,6 +3002,13 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2921 cpu_to_le32(ioc->reply_post_free_dma); 3002 cpu_to_le32(ioc->reply_post_free_dma);
2922#endif 3003#endif
2923 3004
3005 /* This time stamp specifies number of milliseconds
3006 * since epoch ~ midnight January 1, 1970.
3007 */
3008 do_gettimeofday(&current_time);
3009 mpi_request.TimeStamp = (current_time.tv_sec * 1000) +
3010 (current_time.tv_usec >> 3);
3011
2924 if (ioc->logging_level & MPT_DEBUG_INIT) { 3012 if (ioc->logging_level & MPT_DEBUG_INIT) {
2925 u32 *mfp; 3013 u32 *mfp;
2926 int i; 3014 int i;
@@ -2943,7 +3031,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2943 return r; 3031 return r;
2944 } 3032 }
2945 3033
2946 if (mpi_reply.IOCStatus != MPI2_IOCSTATUS_SUCCESS || 3034 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
3035 if (ioc_status != MPI2_IOCSTATUS_SUCCESS ||
2947 mpi_reply.IOCLogInfo) { 3036 mpi_reply.IOCLogInfo) {
2948 printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__); 3037 printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__);
2949 r = -EIO; 3038 r = -EIO;
@@ -3461,11 +3550,11 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3461 return r; 3550 return r;
3462 3551
3463 pci_set_drvdata(ioc->pdev, ioc->shost); 3552 pci_set_drvdata(ioc->pdev, ioc->shost);
3464 r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); 3553 r = _base_get_ioc_facts(ioc, CAN_SLEEP);
3465 if (r) 3554 if (r)
3466 goto out_free_resources; 3555 goto out_free_resources;
3467 3556
3468 r = _base_get_ioc_facts(ioc, CAN_SLEEP); 3557 r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
3469 if (r) 3558 if (r)
3470 goto out_free_resources; 3559 goto out_free_resources;
3471 3560
@@ -3486,6 +3575,8 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3486 3575
3487 init_waitqueue_head(&ioc->reset_wq); 3576 init_waitqueue_head(&ioc->reset_wq);
3488 3577
3578 ioc->fwfault_debug = mpt2sas_fwfault_debug;
3579
3489 /* base internal command bits */ 3580 /* base internal command bits */
3490 mutex_init(&ioc->base_cmds.mutex); 3581 mutex_init(&ioc->base_cmds.mutex);
3491 ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); 3582 ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
@@ -3496,6 +3587,11 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3496 ioc->transport_cmds.status = MPT2_CMD_NOT_USED; 3587 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
3497 mutex_init(&ioc->transport_cmds.mutex); 3588 mutex_init(&ioc->transport_cmds.mutex);
3498 3589
3590 /* scsih internal command bits */
3591 ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3592 ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
3593 mutex_init(&ioc->scsih_cmds.mutex);
3594
3499 /* task management internal command bits */ 3595 /* task management internal command bits */
3500 ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); 3596 ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3501 ioc->tm_cmds.status = MPT2_CMD_NOT_USED; 3597 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
@@ -3531,6 +3627,8 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3531 goto out_free_resources; 3627 goto out_free_resources;
3532 3628
3533 mpt2sas_base_start_watchdog(ioc); 3629 mpt2sas_base_start_watchdog(ioc);
3630 if (diag_buffer_enable != 0)
3631 mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
3534 return 0; 3632 return 0;
3535 3633
3536 out_free_resources: 3634 out_free_resources:
@@ -3684,6 +3782,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, 3782 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
3685 __func__)); 3783 __func__));
3686 3784
3785 if (mpt2sas_fwfault_debug)
3786 mpt2sas_halt_firmware(ioc);
3787
3687 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); 3788 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3688 if (ioc->shost_recovery) { 3789 if (ioc->shost_recovery) {
3689 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); 3790 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);