aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2010-06-17 04:13:17 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-27 13:02:14 -0400
commit570c67ac443dab5c46e5744e950f0539724cb65d (patch)
treedad14200b33f9c0d24c43886b7a88b2a7bf0f2eb /drivers/scsi/mpt2sas
parent203d65b16cfef448dbfb79f66b672be4511fc6a9 (diff)
[SCSI] mpt2sas: Added sysfs support for trace buffer
Added support so the diag ring buffer can be pulled via sysfs Added three new shost attributes: host_trace_buffer, host_trace_buffer_enable, and host_trace_buffer_size. The host_trace_buffer_enable attribute is used to either post or release the trace buffers. The host_trace_buffer_size attribute contains the size of the trace buffer. The host_trace_buffer atttribute contains a maximum 4KB window of the buffer. In order to read the entire host buffer, you will need to write the offset to host_trace_buffer prior to reading it. release the host buffer, then write the entire host buffer contents to a file. In addition to this enhancement, we moved the automatic posting of host buffers at driver load time to be called prior to port_enable, instead of after. That way discovery is available in the host buffer. Signed-off-by: Kashyap Desai <kashyap.desai@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.c10
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c192
3 files changed, 200 insertions, 4 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 88befc798469..93c06239d951 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -3529,8 +3529,12 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3529 if (sleep_flag == CAN_SLEEP) 3529 if (sleep_flag == CAN_SLEEP)
3530 _base_static_config_pages(ioc); 3530 _base_static_config_pages(ioc);
3531 3531
3532 if (ioc->wait_for_port_enable_to_complete && disable_discovery > 0) 3532 if (ioc->wait_for_port_enable_to_complete) {
3533 return r; 3533 if (diag_buffer_enable != 0)
3534 mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
3535 if (disable_discovery > 0)
3536 return r;
3537 }
3534 3538
3535 r = _base_send_port_enable(ioc, sleep_flag); 3539 r = _base_send_port_enable(ioc, sleep_flag);
3536 if (r) 3540 if (r)
@@ -3679,8 +3683,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3679 goto out_free_resources; 3683 goto out_free_resources;
3680 3684
3681 mpt2sas_base_start_watchdog(ioc); 3685 mpt2sas_base_start_watchdog(ioc);
3682 if (diag_buffer_enable != 0)
3683 mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
3684 return 0; 3686 return 0;
3685 3687
3686 out_free_resources: 3688 out_free_resources:
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index a4a731529226..ffe93984e56a 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -750,6 +750,8 @@ struct MPT2SAS_ADAPTER {
750 Mpi2ManufacturingPage10_t manu_pg10; 750 Mpi2ManufacturingPage10_t manu_pg10;
751 u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23]; 751 u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23];
752 u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; 752 u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
753 u32 ring_buffer_offset;
754 u32 ring_buffer_sz;
753}; 755};
754 756
755typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, 757typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 25c866e3e900..371f063a926c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -2603,6 +2603,195 @@ _ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
2603static DEVICE_ATTR(ioc_reset_count, S_IRUGO, 2603static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
2604 _ctl_ioc_reset_count_show, NULL); 2604 _ctl_ioc_reset_count_show, NULL);
2605 2605
2606struct DIAG_BUFFER_START {
2607 u32 Size;
2608 u32 DiagVersion;
2609 u8 BufferType;
2610 u8 Reserved[3];
2611 u32 Reserved1;
2612 u32 Reserved2;
2613 u32 Reserved3;
2614};
2615/**
2616 * _ctl_host_trace_buffer_size_show - host buffer size (trace only)
2617 * @cdev - pointer to embedded class device
2618 * @buf - the buffer returned
2619 *
2620 * A sysfs 'read-only' shost attribute.
2621 */
2622static ssize_t
2623_ctl_host_trace_buffer_size_show(struct device *cdev,
2624 struct device_attribute *attr, char *buf)
2625{
2626 struct Scsi_Host *shost = class_to_shost(cdev);
2627 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2628 u32 size = 0;
2629 struct DIAG_BUFFER_START *request_data;
2630
2631 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
2632 printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
2633 "registered\n", ioc->name, __func__);
2634 return 0;
2635 }
2636
2637 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2638 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
2639 printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
2640 "registered\n", ioc->name, __func__);
2641 return 0;
2642 }
2643
2644 request_data = (struct DIAG_BUFFER_START *)
2645 ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE];
2646 if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
2647 le32_to_cpu(request_data->DiagVersion) == 0x01000000) &&
2648 le32_to_cpu(request_data->Reserved3) == 0x4742444c)
2649 size = le32_to_cpu(request_data->Size);
2650
2651 ioc->ring_buffer_sz = size;
2652 return snprintf(buf, PAGE_SIZE, "%d\n", size);
2653}
2654static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO,
2655 _ctl_host_trace_buffer_size_show, NULL);
2656
2657/**
2658 * _ctl_host_trace_buffer_show - firmware ring buffer (trace only)
2659 * @cdev - pointer to embedded class device
2660 * @buf - the buffer returned
2661 *
2662 * A sysfs 'read/write' shost attribute.
2663 *
2664 * You will only be able to read 4k bytes of ring buffer at a time.
2665 * In order to read beyond 4k bytes, you will have to write out the
2666 * offset to the same attribute, it will move the pointer.
2667 */
2668static ssize_t
2669_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr,
2670 char *buf)
2671{
2672 struct Scsi_Host *shost = class_to_shost(cdev);
2673 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2674 void *request_data;
2675 u32 size;
2676
2677 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
2678 printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
2679 "registered\n", ioc->name, __func__);
2680 return 0;
2681 }
2682
2683 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2684 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
2685 printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
2686 "registered\n", ioc->name, __func__);
2687 return 0;
2688 }
2689
2690 if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
2691 return 0;
2692
2693 size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
2694 size = (size > PAGE_SIZE) ? PAGE_SIZE : size;
2695 request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset;
2696 memcpy(buf, request_data, size);
2697 return size;
2698}
2699
2700static ssize_t
2701_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr,
2702 const char *buf, size_t count)
2703{
2704 struct Scsi_Host *shost = class_to_shost(cdev);
2705 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2706 int val = 0;
2707
2708 if (sscanf(buf, "%d", &val) != 1)
2709 return -EINVAL;
2710
2711 ioc->ring_buffer_offset = val;
2712 return strlen(buf);
2713}
2714static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR,
2715 _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store);
2716
2717/*****************************************/
2718
2719/**
2720 * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only)
2721 * @cdev - pointer to embedded class device
2722 * @buf - the buffer returned
2723 *
2724 * A sysfs 'read/write' shost attribute.
2725 *
2726 * This is a mechnism to post/release host_trace_buffers
2727 */
2728static ssize_t
2729_ctl_host_trace_buffer_enable_show(struct device *cdev,
2730 struct device_attribute *attr, char *buf)
2731{
2732 struct Scsi_Host *shost = class_to_shost(cdev);
2733 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2734
2735 if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) ||
2736 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2737 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0))
2738 return snprintf(buf, PAGE_SIZE, "off\n");
2739 else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2740 MPT2_DIAG_BUFFER_IS_RELEASED))
2741 return snprintf(buf, PAGE_SIZE, "release\n");
2742 else
2743 return snprintf(buf, PAGE_SIZE, "post\n");
2744}
2745
2746static ssize_t
2747_ctl_host_trace_buffer_enable_store(struct device *cdev,
2748 struct device_attribute *attr, const char *buf, size_t count)
2749{
2750 struct Scsi_Host *shost = class_to_shost(cdev);
2751 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2752 char str[10] = "";
2753 struct mpt2_diag_register diag_register;
2754 u8 issue_reset = 0;
2755
2756 if (sscanf(buf, "%s", str) != 1)
2757 return -EINVAL;
2758
2759 if (!strcmp(str, "post")) {
2760 /* exit out if host buffers are already posted */
2761 if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) &&
2762 (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2763 MPT2_DIAG_BUFFER_IS_REGISTERED) &&
2764 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2765 MPT2_DIAG_BUFFER_IS_RELEASED) == 0))
2766 goto out;
2767 memset(&diag_register, 0, sizeof(struct mpt2_diag_register));
2768 printk(MPT2SAS_INFO_FMT "posting host trace buffers\n",
2769 ioc->name);
2770 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
2771 diag_register.requested_buffer_size = (1024 * 1024);
2772 diag_register.unique_id = 0x7075900;
2773 ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
2774 _ctl_diag_register_2(ioc, &diag_register);
2775 } else if (!strcmp(str, "release")) {
2776 /* exit out if host buffers are already released */
2777 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
2778 goto out;
2779 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2780 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0)
2781 goto out;
2782 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2783 MPT2_DIAG_BUFFER_IS_RELEASED))
2784 goto out;
2785 printk(MPT2SAS_INFO_FMT "releasing host trace buffer\n",
2786 ioc->name);
2787 _ctl_send_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, &issue_reset);
2788 }
2789
2790 out:
2791 return strlen(buf);
2792}
2793static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR,
2794 _ctl_host_trace_buffer_enable_show, _ctl_host_trace_buffer_enable_store);
2606 2795
2607struct device_attribute *mpt2sas_host_attrs[] = { 2796struct device_attribute *mpt2sas_host_attrs[] = {
2608 &dev_attr_version_fw, 2797 &dev_attr_version_fw,
@@ -2621,6 +2810,9 @@ struct device_attribute *mpt2sas_host_attrs[] = {
2621 &dev_attr_fw_queue_depth, 2810 &dev_attr_fw_queue_depth,
2622 &dev_attr_host_sas_address, 2811 &dev_attr_host_sas_address,
2623 &dev_attr_ioc_reset_count, 2812 &dev_attr_ioc_reset_count,
2813 &dev_attr_host_trace_buffer_size,
2814 &dev_attr_host_trace_buffer,
2815 &dev_attr_host_trace_buffer_enable,
2624 NULL, 2816 NULL,
2625}; 2817};
2626 2818