diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_ctl.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_ctl.c | 411 |
1 files changed, 353 insertions, 58 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index d88e9756d8f5..b774973f0765 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c | |||
@@ -80,6 +80,32 @@ enum block_state { | |||
80 | BLOCKING, | 80 | BLOCKING, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | /** | ||
84 | * _ctl_sas_device_find_by_handle - sas device search | ||
85 | * @ioc: per adapter object | ||
86 | * @handle: sas device handle (assigned by firmware) | ||
87 | * Context: Calling function should acquire ioc->sas_device_lock | ||
88 | * | ||
89 | * This searches for sas_device based on sas_address, then return sas_device | ||
90 | * object. | ||
91 | */ | ||
92 | static struct _sas_device * | ||
93 | _ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
94 | { | ||
95 | struct _sas_device *sas_device, *r; | ||
96 | |||
97 | r = NULL; | ||
98 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) { | ||
99 | if (sas_device->handle != handle) | ||
100 | continue; | ||
101 | r = sas_device; | ||
102 | goto out; | ||
103 | } | ||
104 | |||
105 | out: | ||
106 | return r; | ||
107 | } | ||
108 | |||
83 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 109 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
84 | /** | 110 | /** |
85 | * _ctl_display_some_debug - debug routine | 111 | * _ctl_display_some_debug - debug routine |
@@ -188,14 +214,14 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
188 | if (!desc) | 214 | if (!desc) |
189 | return; | 215 | return; |
190 | 216 | ||
191 | printk(MPT2SAS_DEBUG_FMT "%s: %s, smid(%d)\n", | 217 | printk(MPT2SAS_INFO_FMT "%s: %s, smid(%d)\n", |
192 | ioc->name, calling_function_name, desc, smid); | 218 | ioc->name, calling_function_name, desc, smid); |
193 | 219 | ||
194 | if (!mpi_reply) | 220 | if (!mpi_reply) |
195 | return; | 221 | return; |
196 | 222 | ||
197 | if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) | 223 | if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) |
198 | printk(MPT2SAS_DEBUG_FMT | 224 | printk(MPT2SAS_INFO_FMT |
199 | "\tiocstatus(0x%04x), loginfo(0x%08x)\n", | 225 | "\tiocstatus(0x%04x), loginfo(0x%08x)\n", |
200 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | 226 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), |
201 | le32_to_cpu(mpi_reply->IOCLogInfo)); | 227 | le32_to_cpu(mpi_reply->IOCLogInfo)); |
@@ -205,8 +231,24 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
205 | MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { | 231 | MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { |
206 | Mpi2SCSIIOReply_t *scsi_reply = | 232 | Mpi2SCSIIOReply_t *scsi_reply = |
207 | (Mpi2SCSIIOReply_t *)mpi_reply; | 233 | (Mpi2SCSIIOReply_t *)mpi_reply; |
234 | struct _sas_device *sas_device = NULL; | ||
235 | unsigned long flags; | ||
236 | |||
237 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
238 | sas_device = _ctl_sas_device_find_by_handle(ioc, | ||
239 | le16_to_cpu(scsi_reply->DevHandle)); | ||
240 | if (sas_device) { | ||
241 | printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), " | ||
242 | "phy(%d)\n", ioc->name, (unsigned long long) | ||
243 | sas_device->sas_address, sas_device->phy); | ||
244 | printk(MPT2SAS_WARN_FMT | ||
245 | "\tenclosure_logical_id(0x%016llx), slot(%d)\n", | ||
246 | ioc->name, sas_device->enclosure_logical_id, | ||
247 | sas_device->slot); | ||
248 | } | ||
249 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
208 | if (scsi_reply->SCSIState || scsi_reply->SCSIStatus) | 250 | if (scsi_reply->SCSIState || scsi_reply->SCSIStatus) |
209 | printk(MPT2SAS_DEBUG_FMT | 251 | printk(MPT2SAS_INFO_FMT |
210 | "\tscsi_state(0x%02x), scsi_status" | 252 | "\tscsi_state(0x%02x), scsi_status" |
211 | "(0x%02x)\n", ioc->name, | 253 | "(0x%02x)\n", ioc->name, |
212 | scsi_reply->SCSIState, | 254 | scsi_reply->SCSIState, |
@@ -233,6 +275,9 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
233 | u32 reply) | 275 | u32 reply) |
234 | { | 276 | { |
235 | MPI2DefaultReply_t *mpi_reply; | 277 | MPI2DefaultReply_t *mpi_reply; |
278 | Mpi2SCSIIOReply_t *scsiio_reply; | ||
279 | const void *sense_data; | ||
280 | u32 sz; | ||
236 | 281 | ||
237 | if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) | 282 | if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) |
238 | return 1; | 283 | return 1; |
@@ -243,6 +288,20 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
243 | if (mpi_reply) { | 288 | if (mpi_reply) { |
244 | memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); | 289 | memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); |
245 | ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID; | 290 | ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID; |
291 | /* get sense data */ | ||
292 | if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || | ||
293 | mpi_reply->Function == | ||
294 | MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { | ||
295 | scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply; | ||
296 | if (scsiio_reply->SCSIState & | ||
297 | MPI2_SCSI_STATE_AUTOSENSE_VALID) { | ||
298 | sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, | ||
299 | le32_to_cpu(scsiio_reply->SenseCount)); | ||
300 | sense_data = mpt2sas_base_get_sense_buffer(ioc, | ||
301 | smid); | ||
302 | memcpy(ioc->ctl_cmds.sense, sense_data, sz); | ||
303 | } | ||
304 | } | ||
246 | } | 305 | } |
247 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 306 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
248 | _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply); | 307 | _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply); |
@@ -392,7 +451,7 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
392 | 451 | ||
393 | switch (reset_phase) { | 452 | switch (reset_phase) { |
394 | case MPT2_IOC_PRE_RESET: | 453 | case MPT2_IOC_PRE_RESET: |
395 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 454 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " |
396 | "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); | 455 | "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); |
397 | for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { | 456 | for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { |
398 | if (!(ioc->diag_buffer_status[i] & | 457 | if (!(ioc->diag_buffer_status[i] & |
@@ -405,7 +464,7 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
405 | } | 464 | } |
406 | break; | 465 | break; |
407 | case MPT2_IOC_AFTER_RESET: | 466 | case MPT2_IOC_AFTER_RESET: |
408 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 467 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " |
409 | "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); | 468 | "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); |
410 | if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) { | 469 | if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) { |
411 | ioc->ctl_cmds.status |= MPT2_CMD_RESET; | 470 | ioc->ctl_cmds.status |= MPT2_CMD_RESET; |
@@ -414,7 +473,7 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
414 | } | 473 | } |
415 | break; | 474 | break; |
416 | case MPT2_IOC_DONE_RESET: | 475 | case MPT2_IOC_DONE_RESET: |
417 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 476 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " |
418 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); | 477 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); |
419 | 478 | ||
420 | for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { | 479 | for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { |
@@ -531,7 +590,7 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, | |||
531 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 590 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
532 | 591 | ||
533 | if (!found) { | 592 | if (!found) { |
534 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 593 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " |
535 | "handle(0x%04x), lun(%d), no active mid!!\n", ioc->name, | 594 | "handle(0x%04x), lun(%d), no active mid!!\n", ioc->name, |
536 | desc, le16_to_cpu(tm_request->DevHandle), lun)); | 595 | desc, le16_to_cpu(tm_request->DevHandle), lun)); |
537 | tm_reply = ioc->ctl_cmds.reply; | 596 | tm_reply = ioc->ctl_cmds.reply; |
@@ -549,7 +608,7 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, | |||
549 | return 1; | 608 | return 1; |
550 | } | 609 | } |
551 | 610 | ||
552 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 611 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " |
553 | "handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name, | 612 | "handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name, |
554 | desc, le16_to_cpu(tm_request->DevHandle), lun, | 613 | desc, le16_to_cpu(tm_request->DevHandle), lun, |
555 | le16_to_cpu(tm_request->TaskMID))); | 614 | le16_to_cpu(tm_request->TaskMID))); |
@@ -567,7 +626,7 @@ static long | |||
567 | _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | 626 | _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, |
568 | struct mpt2_ioctl_command karg, void __user *mf, enum block_state state) | 627 | struct mpt2_ioctl_command karg, void __user *mf, enum block_state state) |
569 | { | 628 | { |
570 | MPI2RequestHeader_t *mpi_request; | 629 | MPI2RequestHeader_t *mpi_request = NULL, *request; |
571 | MPI2DefaultReply_t *mpi_reply; | 630 | MPI2DefaultReply_t *mpi_reply; |
572 | u32 ioc_state; | 631 | u32 ioc_state; |
573 | u16 ioc_status; | 632 | u16 ioc_status; |
@@ -576,7 +635,6 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
576 | u8 issue_reset; | 635 | u8 issue_reset; |
577 | u32 sz; | 636 | u32 sz; |
578 | void *psge; | 637 | void *psge; |
579 | void *priv_sense = NULL; | ||
580 | void *data_out = NULL; | 638 | void *data_out = NULL; |
581 | dma_addr_t data_out_dma; | 639 | dma_addr_t data_out_dma; |
582 | size_t data_out_sz = 0; | 640 | size_t data_out_sz = 0; |
@@ -621,31 +679,50 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
621 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | 679 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", |
622 | ioc->name, __func__); | 680 | ioc->name, __func__); |
623 | 681 | ||
624 | smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL); | 682 | mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL); |
625 | if (!smid) { | 683 | if (!mpi_request) { |
626 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | 684 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a memory for " |
627 | ioc->name, __func__); | 685 | "mpi_request\n", ioc->name, __func__); |
628 | ret = -EAGAIN; | 686 | ret = -ENOMEM; |
629 | goto out; | 687 | goto out; |
630 | } | 688 | } |
631 | 689 | ||
632 | ret = 0; | ||
633 | ioc->ctl_cmds.status = MPT2_CMD_PENDING; | ||
634 | memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); | ||
635 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
636 | ioc->ctl_cmds.smid = smid; | ||
637 | data_out_sz = karg.data_out_size; | ||
638 | data_in_sz = karg.data_in_size; | ||
639 | |||
640 | /* copy in request message frame from user */ | 690 | /* copy in request message frame from user */ |
641 | if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { | 691 | if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { |
642 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, | 692 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, |
643 | __func__); | 693 | __func__); |
644 | ret = -EFAULT; | 694 | ret = -EFAULT; |
645 | mpt2sas_base_free_smid(ioc, smid); | ||
646 | goto out; | 695 | goto out; |
647 | } | 696 | } |
648 | 697 | ||
698 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { | ||
699 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx); | ||
700 | if (!smid) { | ||
701 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
702 | ioc->name, __func__); | ||
703 | ret = -EAGAIN; | ||
704 | goto out; | ||
705 | } | ||
706 | } else { | ||
707 | |||
708 | smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL); | ||
709 | if (!smid) { | ||
710 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
711 | ioc->name, __func__); | ||
712 | ret = -EAGAIN; | ||
713 | goto out; | ||
714 | } | ||
715 | } | ||
716 | |||
717 | ret = 0; | ||
718 | ioc->ctl_cmds.status = MPT2_CMD_PENDING; | ||
719 | memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); | ||
720 | request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
721 | memcpy(request, mpi_request, karg.data_sge_offset*4); | ||
722 | ioc->ctl_cmds.smid = smid; | ||
723 | data_out_sz = karg.data_out_size; | ||
724 | data_in_sz = karg.data_in_size; | ||
725 | |||
649 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || | 726 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || |
650 | mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { | 727 | mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { |
651 | if (!le16_to_cpu(mpi_request->FunctionDependent1) || | 728 | if (!le16_to_cpu(mpi_request->FunctionDependent1) || |
@@ -691,7 +768,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
691 | } | 768 | } |
692 | 769 | ||
693 | /* add scatter gather elements */ | 770 | /* add scatter gather elements */ |
694 | psge = (void *)mpi_request + (karg.data_sge_offset*4); | 771 | psge = (void *)request + (karg.data_sge_offset*4); |
695 | 772 | ||
696 | if (!data_out_sz && !data_in_sz) { | 773 | if (!data_out_sz && !data_in_sz) { |
697 | mpt2sas_base_build_zero_len_sge(ioc, psge); | 774 | mpt2sas_base_build_zero_len_sge(ioc, psge); |
@@ -739,11 +816,11 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
739 | case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: | 816 | case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: |
740 | { | 817 | { |
741 | Mpi2SCSIIORequest_t *scsiio_request = | 818 | Mpi2SCSIIORequest_t *scsiio_request = |
742 | (Mpi2SCSIIORequest_t *)mpi_request; | 819 | (Mpi2SCSIIORequest_t *)request; |
820 | scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; | ||
743 | scsiio_request->SenseBufferLowAddress = | 821 | scsiio_request->SenseBufferLowAddress = |
744 | mpt2sas_base_get_sense_buffer_dma(ioc, smid); | 822 | mpt2sas_base_get_sense_buffer_dma(ioc, smid); |
745 | priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid); | 823 | memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE); |
746 | memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE); | ||
747 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) | 824 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) |
748 | mpt2sas_base_put_smid_scsi_io(ioc, smid, | 825 | mpt2sas_base_put_smid_scsi_io(ioc, smid, |
749 | le16_to_cpu(mpi_request->FunctionDependent1)); | 826 | le16_to_cpu(mpi_request->FunctionDependent1)); |
@@ -754,9 +831,9 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
754 | case MPI2_FUNCTION_SCSI_TASK_MGMT: | 831 | case MPI2_FUNCTION_SCSI_TASK_MGMT: |
755 | { | 832 | { |
756 | Mpi2SCSITaskManagementRequest_t *tm_request = | 833 | Mpi2SCSITaskManagementRequest_t *tm_request = |
757 | (Mpi2SCSITaskManagementRequest_t *)mpi_request; | 834 | (Mpi2SCSITaskManagementRequest_t *)request; |
758 | 835 | ||
759 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: " | 836 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "TASK_MGMT: " |
760 | "handle(0x%04x), task_type(0x%02x)\n", ioc->name, | 837 | "handle(0x%04x), task_type(0x%02x)\n", ioc->name, |
761 | le16_to_cpu(tm_request->DevHandle), tm_request->TaskType)); | 838 | le16_to_cpu(tm_request->DevHandle), tm_request->TaskType)); |
762 | 839 | ||
@@ -851,7 +928,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
851 | Mpi2SCSITaskManagementReply_t *tm_reply = | 928 | Mpi2SCSITaskManagementReply_t *tm_reply = |
852 | (Mpi2SCSITaskManagementReply_t *)mpi_reply; | 929 | (Mpi2SCSITaskManagementReply_t *)mpi_reply; |
853 | 930 | ||
854 | printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: " | 931 | printk(MPT2SAS_INFO_FMT "TASK_MGMT: " |
855 | "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " | 932 | "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " |
856 | "TerminationCount(0x%08x)\n", ioc->name, | 933 | "TerminationCount(0x%08x)\n", ioc->name, |
857 | le16_to_cpu(tm_reply->IOCStatus), | 934 | le16_to_cpu(tm_reply->IOCStatus), |
@@ -887,7 +964,8 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
887 | MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function == | 964 | MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function == |
888 | MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { | 965 | MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { |
889 | sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE); | 966 | sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE); |
890 | if (copy_to_user(karg.sense_data_ptr, priv_sense, sz)) { | 967 | if (copy_to_user(karg.sense_data_ptr, |
968 | ioc->ctl_cmds.sense, sz)) { | ||
891 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, | 969 | printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, |
892 | __LINE__, __func__); | 970 | __LINE__, __func__); |
893 | ret = -ENODATA; | 971 | ret = -ENODATA; |
@@ -926,6 +1004,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
926 | pci_free_consistent(ioc->pdev, data_out_sz, data_out, | 1004 | pci_free_consistent(ioc->pdev, data_out_sz, data_out, |
927 | data_out_dma); | 1005 | data_out_dma); |
928 | 1006 | ||
1007 | kfree(mpi_request); | ||
929 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | 1008 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; |
930 | mutex_unlock(&ioc->ctl_cmds.mutex); | 1009 | mutex_unlock(&ioc->ctl_cmds.mutex); |
931 | return ret; | 1010 | return ret; |
@@ -950,7 +1029,7 @@ _ctl_getiocinfo(void __user *arg) | |||
950 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1029 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
951 | return -ENODEV; | 1030 | return -ENODEV; |
952 | 1031 | ||
953 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, | 1032 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, |
954 | __func__)); | 1033 | __func__)); |
955 | 1034 | ||
956 | memset(&karg, 0 , sizeof(karg)); | 1035 | memset(&karg, 0 , sizeof(karg)); |
@@ -998,7 +1077,7 @@ _ctl_eventquery(void __user *arg) | |||
998 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1077 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
999 | return -ENODEV; | 1078 | return -ENODEV; |
1000 | 1079 | ||
1001 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, | 1080 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, |
1002 | __func__)); | 1081 | __func__)); |
1003 | 1082 | ||
1004 | karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE; | 1083 | karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE; |
@@ -1031,7 +1110,7 @@ _ctl_eventenable(void __user *arg) | |||
1031 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1110 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
1032 | return -ENODEV; | 1111 | return -ENODEV; |
1033 | 1112 | ||
1034 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, | 1113 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, |
1035 | __func__)); | 1114 | __func__)); |
1036 | 1115 | ||
1037 | if (ioc->event_log) | 1116 | if (ioc->event_log) |
@@ -1073,7 +1152,7 @@ _ctl_eventreport(void __user *arg) | |||
1073 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1152 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
1074 | return -ENODEV; | 1153 | return -ENODEV; |
1075 | 1154 | ||
1076 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, | 1155 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, |
1077 | __func__)); | 1156 | __func__)); |
1078 | 1157 | ||
1079 | number_bytes = karg.hdr.max_data_size - | 1158 | number_bytes = karg.hdr.max_data_size - |
@@ -1118,7 +1197,7 @@ _ctl_do_reset(void __user *arg) | |||
1118 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1197 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
1119 | return -ENODEV; | 1198 | return -ENODEV; |
1120 | 1199 | ||
1121 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, | 1200 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, |
1122 | __func__)); | 1201 | __func__)); |
1123 | 1202 | ||
1124 | retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 1203 | retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, |
@@ -1219,7 +1298,7 @@ _ctl_btdh_mapping(void __user *arg) | |||
1219 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1298 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
1220 | return -ENODEV; | 1299 | return -ENODEV; |
1221 | 1300 | ||
1222 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1301 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
1223 | __func__)); | 1302 | __func__)); |
1224 | 1303 | ||
1225 | rc = _ctl_btdh_search_sas_device(ioc, &karg); | 1304 | rc = _ctl_btdh_search_sas_device(ioc, &karg); |
@@ -1288,7 +1367,7 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc, | |||
1288 | u16 ioc_status; | 1367 | u16 ioc_status; |
1289 | u8 issue_reset = 0; | 1368 | u8 issue_reset = 0; |
1290 | 1369 | ||
1291 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1370 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
1292 | __func__)); | 1371 | __func__)); |
1293 | 1372 | ||
1294 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { | 1373 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { |
@@ -1376,7 +1455,7 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc, | |||
1376 | mpi_request->VF_ID = 0; /* TODO */ | 1455 | mpi_request->VF_ID = 0; /* TODO */ |
1377 | mpi_request->VP_ID = 0; | 1456 | mpi_request->VP_ID = 0; |
1378 | 1457 | ||
1379 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), " | 1458 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(0x%p), " |
1380 | "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data, | 1459 | "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data, |
1381 | (unsigned long long)request_data_dma, | 1460 | (unsigned long long)request_data_dma, |
1382 | le32_to_cpu(mpi_request->BufferLength))); | 1461 | le32_to_cpu(mpi_request->BufferLength))); |
@@ -1414,10 +1493,10 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc, | |||
1414 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | 1493 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { |
1415 | ioc->diag_buffer_status[buffer_type] |= | 1494 | ioc->diag_buffer_status[buffer_type] |= |
1416 | MPT2_DIAG_BUFFER_IS_REGISTERED; | 1495 | MPT2_DIAG_BUFFER_IS_REGISTERED; |
1417 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n", | 1496 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n", |
1418 | ioc->name, __func__)); | 1497 | ioc->name, __func__)); |
1419 | } else { | 1498 | } else { |
1420 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " | 1499 | printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) " |
1421 | "log_info(0x%08x)\n", ioc->name, __func__, | 1500 | "log_info(0x%08x)\n", ioc->name, __func__, |
1422 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); | 1501 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); |
1423 | rc = -EFAULT; | 1502 | rc = -EFAULT; |
@@ -1541,7 +1620,7 @@ _ctl_diag_unregister(void __user *arg) | |||
1541 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1620 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
1542 | return -ENODEV; | 1621 | return -ENODEV; |
1543 | 1622 | ||
1544 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1623 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
1545 | __func__)); | 1624 | __func__)); |
1546 | 1625 | ||
1547 | buffer_type = karg.unique_id & 0x000000ff; | 1626 | buffer_type = karg.unique_id & 0x000000ff; |
@@ -1611,7 +1690,7 @@ _ctl_diag_query(void __user *arg) | |||
1611 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1690 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
1612 | return -ENODEV; | 1691 | return -ENODEV; |
1613 | 1692 | ||
1614 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1693 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
1615 | __func__)); | 1694 | __func__)); |
1616 | 1695 | ||
1617 | karg.application_flags = 0; | 1696 | karg.application_flags = 0; |
@@ -1689,7 +1768,7 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) | |||
1689 | int rc; | 1768 | int rc; |
1690 | unsigned long timeleft; | 1769 | unsigned long timeleft; |
1691 | 1770 | ||
1692 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1771 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
1693 | __func__)); | 1772 | __func__)); |
1694 | 1773 | ||
1695 | rc = 0; | 1774 | rc = 0; |
@@ -1697,7 +1776,7 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) | |||
1697 | 1776 | ||
1698 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | 1777 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); |
1699 | if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | 1778 | if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { |
1700 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 1779 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " |
1701 | "skipping due to FAULT state\n", ioc->name, | 1780 | "skipping due to FAULT state\n", ioc->name, |
1702 | __func__)); | 1781 | __func__)); |
1703 | rc = -EAGAIN; | 1782 | rc = -EAGAIN; |
@@ -1759,10 +1838,10 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) | |||
1759 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | 1838 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { |
1760 | ioc->diag_buffer_status[buffer_type] |= | 1839 | ioc->diag_buffer_status[buffer_type] |= |
1761 | MPT2_DIAG_BUFFER_IS_RELEASED; | 1840 | MPT2_DIAG_BUFFER_IS_RELEASED; |
1762 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n", | 1841 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n", |
1763 | ioc->name, __func__)); | 1842 | ioc->name, __func__)); |
1764 | } else { | 1843 | } else { |
1765 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " | 1844 | printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) " |
1766 | "log_info(0x%08x)\n", ioc->name, __func__, | 1845 | "log_info(0x%08x)\n", ioc->name, __func__, |
1767 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); | 1846 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); |
1768 | rc = -EFAULT; | 1847 | rc = -EFAULT; |
@@ -1800,7 +1879,7 @@ _ctl_diag_release(void __user *arg, enum block_state state) | |||
1800 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1879 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
1801 | return -ENODEV; | 1880 | return -ENODEV; |
1802 | 1881 | ||
1803 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1882 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
1804 | __func__)); | 1883 | __func__)); |
1805 | 1884 | ||
1806 | buffer_type = karg.unique_id & 0x000000ff; | 1885 | buffer_type = karg.unique_id & 0x000000ff; |
@@ -1896,7 +1975,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
1896 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | 1975 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) |
1897 | return -ENODEV; | 1976 | return -ENODEV; |
1898 | 1977 | ||
1899 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1978 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
1900 | __func__)); | 1979 | __func__)); |
1901 | 1980 | ||
1902 | buffer_type = karg.unique_id & 0x000000ff; | 1981 | buffer_type = karg.unique_id & 0x000000ff; |
@@ -1927,7 +2006,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
1927 | } | 2006 | } |
1928 | 2007 | ||
1929 | diag_data = (void *)(request_data + karg.starting_offset); | 2008 | diag_data = (void *)(request_data + karg.starting_offset); |
1930 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(%p), " | 2009 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), " |
1931 | "offset(%d), sz(%d)\n", ioc->name, __func__, | 2010 | "offset(%d), sz(%d)\n", ioc->name, __func__, |
1932 | diag_data, karg.starting_offset, karg.bytes_to_read)); | 2011 | diag_data, karg.starting_offset, karg.bytes_to_read)); |
1933 | 2012 | ||
@@ -1942,11 +2021,11 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
1942 | if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0) | 2021 | if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0) |
1943 | return 0; | 2022 | return 0; |
1944 | 2023 | ||
1945 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: Reregister " | 2024 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: Reregister " |
1946 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type)); | 2025 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type)); |
1947 | if ((ioc->diag_buffer_status[buffer_type] & | 2026 | if ((ioc->diag_buffer_status[buffer_type] & |
1948 | MPT2_DIAG_BUFFER_IS_RELEASED) == 0) { | 2027 | MPT2_DIAG_BUFFER_IS_RELEASED) == 0) { |
1949 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 2028 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " |
1950 | "buffer_type(0x%02x) is still registered\n", ioc->name, | 2029 | "buffer_type(0x%02x) is still registered\n", ioc->name, |
1951 | __func__, buffer_type)); | 2030 | __func__, buffer_type)); |
1952 | return 0; | 2031 | return 0; |
@@ -2020,10 +2099,10 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
2020 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | 2099 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { |
2021 | ioc->diag_buffer_status[buffer_type] |= | 2100 | ioc->diag_buffer_status[buffer_type] |= |
2022 | MPT2_DIAG_BUFFER_IS_REGISTERED; | 2101 | MPT2_DIAG_BUFFER_IS_REGISTERED; |
2023 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n", | 2102 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n", |
2024 | ioc->name, __func__)); | 2103 | ioc->name, __func__)); |
2025 | } else { | 2104 | } else { |
2026 | printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " | 2105 | printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) " |
2027 | "log_info(0x%08x)\n", ioc->name, __func__, | 2106 | "log_info(0x%08x)\n", ioc->name, __func__, |
2028 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); | 2107 | ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); |
2029 | rc = -EFAULT; | 2108 | rc = -EFAULT; |
@@ -2077,7 +2156,7 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg) | |||
2077 | !ioc) | 2156 | !ioc) |
2078 | return -ENODEV; | 2157 | return -ENODEV; |
2079 | 2158 | ||
2080 | if (ioc->shost_recovery) | 2159 | if (ioc->shost_recovery || ioc->pci_error_recovery) |
2081 | return -EAGAIN; | 2160 | return -EAGAIN; |
2082 | 2161 | ||
2083 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) { | 2162 | if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) { |
@@ -2140,7 +2219,7 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg) | |||
2140 | !ioc) | 2219 | !ioc) |
2141 | return -ENODEV; | 2220 | return -ENODEV; |
2142 | 2221 | ||
2143 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT | 2222 | dctlprintk(ioc, printk(MPT2SAS_INFO_FMT |
2144 | "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd)); | 2223 | "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd)); |
2145 | break; | 2224 | break; |
2146 | } | 2225 | } |
@@ -2196,7 +2275,7 @@ _ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg) | |||
2196 | if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc) | 2275 | if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc) |
2197 | return -ENODEV; | 2276 | return -ENODEV; |
2198 | 2277 | ||
2199 | if (ioc->shost_recovery) | 2278 | if (ioc->shost_recovery || ioc->pci_error_recovery) |
2200 | return -EAGAIN; | 2279 | return -EAGAIN; |
2201 | 2280 | ||
2202 | memset(&karg, 0, sizeof(struct mpt2_ioctl_command)); | 2281 | memset(&karg, 0, sizeof(struct mpt2_ioctl_command)); |
@@ -2581,6 +2660,218 @@ _ctl_fwfault_debug_store(struct device *cdev, | |||
2581 | static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR, | 2660 | static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR, |
2582 | _ctl_fwfault_debug_show, _ctl_fwfault_debug_store); | 2661 | _ctl_fwfault_debug_show, _ctl_fwfault_debug_store); |
2583 | 2662 | ||
2663 | |||
2664 | /** | ||
2665 | * _ctl_ioc_reset_count_show - ioc reset count | ||
2666 | * @cdev - pointer to embedded class device | ||
2667 | * @buf - the buffer returned | ||
2668 | * | ||
2669 | * This is firmware queue depth limit | ||
2670 | * | ||
2671 | * A sysfs 'read-only' shost attribute. | ||
2672 | */ | ||
2673 | static ssize_t | ||
2674 | _ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr, | ||
2675 | char *buf) | ||
2676 | { | ||
2677 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
2678 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
2679 | |||
2680 | return snprintf(buf, PAGE_SIZE, "%08d\n", ioc->ioc_reset_count); | ||
2681 | } | ||
2682 | static DEVICE_ATTR(ioc_reset_count, S_IRUGO, | ||
2683 | _ctl_ioc_reset_count_show, NULL); | ||
2684 | |||
2685 | struct DIAG_BUFFER_START { | ||
2686 | u32 Size; | ||
2687 | u32 DiagVersion; | ||
2688 | u8 BufferType; | ||
2689 | u8 Reserved[3]; | ||
2690 | u32 Reserved1; | ||
2691 | u32 Reserved2; | ||
2692 | u32 Reserved3; | ||
2693 | }; | ||
2694 | /** | ||
2695 | * _ctl_host_trace_buffer_size_show - host buffer size (trace only) | ||
2696 | * @cdev - pointer to embedded class device | ||
2697 | * @buf - the buffer returned | ||
2698 | * | ||
2699 | * A sysfs 'read-only' shost attribute. | ||
2700 | */ | ||
2701 | static ssize_t | ||
2702 | _ctl_host_trace_buffer_size_show(struct device *cdev, | ||
2703 | struct device_attribute *attr, char *buf) | ||
2704 | { | ||
2705 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
2706 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
2707 | u32 size = 0; | ||
2708 | struct DIAG_BUFFER_START *request_data; | ||
2709 | |||
2710 | if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { | ||
2711 | printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " | ||
2712 | "registered\n", ioc->name, __func__); | ||
2713 | return 0; | ||
2714 | } | ||
2715 | |||
2716 | if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
2717 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { | ||
2718 | printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " | ||
2719 | "registered\n", ioc->name, __func__); | ||
2720 | return 0; | ||
2721 | } | ||
2722 | |||
2723 | request_data = (struct DIAG_BUFFER_START *) | ||
2724 | ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]; | ||
2725 | if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 || | ||
2726 | le32_to_cpu(request_data->DiagVersion) == 0x01000000) && | ||
2727 | le32_to_cpu(request_data->Reserved3) == 0x4742444c) | ||
2728 | size = le32_to_cpu(request_data->Size); | ||
2729 | |||
2730 | ioc->ring_buffer_sz = size; | ||
2731 | return snprintf(buf, PAGE_SIZE, "%d\n", size); | ||
2732 | } | ||
2733 | static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO, | ||
2734 | _ctl_host_trace_buffer_size_show, NULL); | ||
2735 | |||
2736 | /** | ||
2737 | * _ctl_host_trace_buffer_show - firmware ring buffer (trace only) | ||
2738 | * @cdev - pointer to embedded class device | ||
2739 | * @buf - the buffer returned | ||
2740 | * | ||
2741 | * A sysfs 'read/write' shost attribute. | ||
2742 | * | ||
2743 | * You will only be able to read 4k bytes of ring buffer at a time. | ||
2744 | * In order to read beyond 4k bytes, you will have to write out the | ||
2745 | * offset to the same attribute, it will move the pointer. | ||
2746 | */ | ||
2747 | static ssize_t | ||
2748 | _ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr, | ||
2749 | char *buf) | ||
2750 | { | ||
2751 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
2752 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
2753 | void *request_data; | ||
2754 | u32 size; | ||
2755 | |||
2756 | if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { | ||
2757 | printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " | ||
2758 | "registered\n", ioc->name, __func__); | ||
2759 | return 0; | ||
2760 | } | ||
2761 | |||
2762 | if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
2763 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { | ||
2764 | printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " | ||
2765 | "registered\n", ioc->name, __func__); | ||
2766 | return 0; | ||
2767 | } | ||
2768 | |||
2769 | if (ioc->ring_buffer_offset > ioc->ring_buffer_sz) | ||
2770 | return 0; | ||
2771 | |||
2772 | size = ioc->ring_buffer_sz - ioc->ring_buffer_offset; | ||
2773 | size = (size > PAGE_SIZE) ? PAGE_SIZE : size; | ||
2774 | request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset; | ||
2775 | memcpy(buf, request_data, size); | ||
2776 | return size; | ||
2777 | } | ||
2778 | |||
2779 | static ssize_t | ||
2780 | _ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr, | ||
2781 | const char *buf, size_t count) | ||
2782 | { | ||
2783 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
2784 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
2785 | int val = 0; | ||
2786 | |||
2787 | if (sscanf(buf, "%d", &val) != 1) | ||
2788 | return -EINVAL; | ||
2789 | |||
2790 | ioc->ring_buffer_offset = val; | ||
2791 | return strlen(buf); | ||
2792 | } | ||
2793 | static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR, | ||
2794 | _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store); | ||
2795 | |||
2796 | /*****************************************/ | ||
2797 | |||
2798 | /** | ||
2799 | * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only) | ||
2800 | * @cdev - pointer to embedded class device | ||
2801 | * @buf - the buffer returned | ||
2802 | * | ||
2803 | * A sysfs 'read/write' shost attribute. | ||
2804 | * | ||
2805 | * This is a mechnism to post/release host_trace_buffers | ||
2806 | */ | ||
2807 | static ssize_t | ||
2808 | _ctl_host_trace_buffer_enable_show(struct device *cdev, | ||
2809 | struct device_attribute *attr, char *buf) | ||
2810 | { | ||
2811 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
2812 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
2813 | |||
2814 | if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) || | ||
2815 | ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
2816 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0)) | ||
2817 | return snprintf(buf, PAGE_SIZE, "off\n"); | ||
2818 | else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
2819 | MPT2_DIAG_BUFFER_IS_RELEASED)) | ||
2820 | return snprintf(buf, PAGE_SIZE, "release\n"); | ||
2821 | else | ||
2822 | return snprintf(buf, PAGE_SIZE, "post\n"); | ||
2823 | } | ||
2824 | |||
2825 | static ssize_t | ||
2826 | _ctl_host_trace_buffer_enable_store(struct device *cdev, | ||
2827 | struct device_attribute *attr, const char *buf, size_t count) | ||
2828 | { | ||
2829 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
2830 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
2831 | char str[10] = ""; | ||
2832 | struct mpt2_diag_register diag_register; | ||
2833 | u8 issue_reset = 0; | ||
2834 | |||
2835 | if (sscanf(buf, "%s", str) != 1) | ||
2836 | return -EINVAL; | ||
2837 | |||
2838 | if (!strcmp(str, "post")) { | ||
2839 | /* exit out if host buffers are already posted */ | ||
2840 | if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) && | ||
2841 | (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
2842 | MPT2_DIAG_BUFFER_IS_REGISTERED) && | ||
2843 | ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
2844 | MPT2_DIAG_BUFFER_IS_RELEASED) == 0)) | ||
2845 | goto out; | ||
2846 | memset(&diag_register, 0, sizeof(struct mpt2_diag_register)); | ||
2847 | printk(MPT2SAS_INFO_FMT "posting host trace buffers\n", | ||
2848 | ioc->name); | ||
2849 | diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE; | ||
2850 | diag_register.requested_buffer_size = (1024 * 1024); | ||
2851 | diag_register.unique_id = 0x7075900; | ||
2852 | ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0; | ||
2853 | _ctl_diag_register_2(ioc, &diag_register); | ||
2854 | } else if (!strcmp(str, "release")) { | ||
2855 | /* exit out if host buffers are already released */ | ||
2856 | if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) | ||
2857 | goto out; | ||
2858 | if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
2859 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) | ||
2860 | goto out; | ||
2861 | if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & | ||
2862 | MPT2_DIAG_BUFFER_IS_RELEASED)) | ||
2863 | goto out; | ||
2864 | printk(MPT2SAS_INFO_FMT "releasing host trace buffer\n", | ||
2865 | ioc->name); | ||
2866 | _ctl_send_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, &issue_reset); | ||
2867 | } | ||
2868 | |||
2869 | out: | ||
2870 | return strlen(buf); | ||
2871 | } | ||
2872 | static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR, | ||
2873 | _ctl_host_trace_buffer_enable_show, _ctl_host_trace_buffer_enable_store); | ||
2874 | |||
2584 | struct device_attribute *mpt2sas_host_attrs[] = { | 2875 | struct device_attribute *mpt2sas_host_attrs[] = { |
2585 | &dev_attr_version_fw, | 2876 | &dev_attr_version_fw, |
2586 | &dev_attr_version_bios, | 2877 | &dev_attr_version_bios, |
@@ -2597,6 +2888,10 @@ struct device_attribute *mpt2sas_host_attrs[] = { | |||
2597 | &dev_attr_fwfault_debug, | 2888 | &dev_attr_fwfault_debug, |
2598 | &dev_attr_fw_queue_depth, | 2889 | &dev_attr_fw_queue_depth, |
2599 | &dev_attr_host_sas_address, | 2890 | &dev_attr_host_sas_address, |
2891 | &dev_attr_ioc_reset_count, | ||
2892 | &dev_attr_host_trace_buffer_size, | ||
2893 | &dev_attr_host_trace_buffer, | ||
2894 | &dev_attr_host_trace_buffer_enable, | ||
2600 | NULL, | 2895 | NULL, |
2601 | }; | 2896 | }; |
2602 | 2897 | ||