diff options
author | Xiangliang Yu <yuxiangl@marvell.com> | 2011-05-24 10:31:47 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-26 02:33:11 -0400 |
commit | 83c7b61cf49c2659829050fec240601415c7f9d9 (patch) | |
tree | 44dda12fb01e6e6d4e1a3e9b0f9994ed72b16c00 /drivers | |
parent | f1f82a919d7fff21ee8c0ef4b9731fb38f2a65db (diff) |
[SCSI] mvsas: Add driver version and interrupt coalescing to device attributes in sysfs
Signed-off-by: Xiangliang Yu <yuxiangl@marvell.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/mvsas/mv_64xx.c | 25 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_94xx.c | 26 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_init.c | 75 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.h | 2 |
4 files changed, 126 insertions, 2 deletions
diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c index 0e13e6441da7..c88b8a7ed398 100644 --- a/drivers/scsi/mvsas/mv_64xx.c +++ b/drivers/scsi/mvsas/mv_64xx.c | |||
@@ -402,7 +402,7 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi) | |||
402 | tmp = 0; | 402 | tmp = 0; |
403 | mw32(MVS_INT_COAL, tmp); | 403 | mw32(MVS_INT_COAL, tmp); |
404 | 404 | ||
405 | tmp = 0x100; | 405 | tmp = 0x10000 | interrupt_coalescing; |
406 | mw32(MVS_INT_COAL_TMOUT, tmp); | 406 | mw32(MVS_INT_COAL_TMOUT, tmp); |
407 | 407 | ||
408 | /* ladies and gentlemen, start your engines */ | 408 | /* ladies and gentlemen, start your engines */ |
@@ -758,6 +758,28 @@ void mvs_64xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd) | |||
758 | } | 758 | } |
759 | #endif | 759 | #endif |
760 | 760 | ||
761 | static void mvs_64xx_tune_interrupt(struct mvs_info *mvi, u32 time) | ||
762 | { | ||
763 | void __iomem *regs = mvi->regs; | ||
764 | u32 tmp = 0; | ||
765 | /* interrupt coalescing may cause missing HW interrput in some case, | ||
766 | * and the max count is 0x1ff, while our max slot is 0x200, | ||
767 | * it will make count 0. | ||
768 | */ | ||
769 | if (time == 0) { | ||
770 | mw32(MVS_INT_COAL, 0); | ||
771 | mw32(MVS_INT_COAL_TMOUT, 0x10000); | ||
772 | } else { | ||
773 | if (MVS_CHIP_SLOT_SZ > 0x1ff) | ||
774 | mw32(MVS_INT_COAL, 0x1ff|COAL_EN); | ||
775 | else | ||
776 | mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN); | ||
777 | |||
778 | tmp = 0x10000 | time; | ||
779 | mw32(MVS_INT_COAL_TMOUT, tmp); | ||
780 | } | ||
781 | } | ||
782 | |||
761 | const struct mvs_dispatch mvs_64xx_dispatch = { | 783 | const struct mvs_dispatch mvs_64xx_dispatch = { |
762 | "mv64xx", | 784 | "mv64xx", |
763 | mvs_64xx_init, | 785 | mvs_64xx_init, |
@@ -811,6 +833,7 @@ const struct mvs_dispatch mvs_64xx_dispatch = { | |||
811 | #ifndef DISABLE_HOTPLUG_DMA_FIX | 833 | #ifndef DISABLE_HOTPLUG_DMA_FIX |
812 | mvs_64xx_fix_dma, | 834 | mvs_64xx_fix_dma, |
813 | #endif | 835 | #endif |
836 | mvs_64xx_tune_interrupt, | ||
814 | NULL, | 837 | NULL, |
815 | }; | 838 | }; |
816 | 839 | ||
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index 3f2ad934c917..e589f31cb2b4 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c | |||
@@ -475,7 +475,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) | |||
475 | tmp = 0; | 475 | tmp = 0; |
476 | mw32(MVS_INT_COAL, tmp); | 476 | mw32(MVS_INT_COAL, tmp); |
477 | 477 | ||
478 | tmp = 0x100; | 478 | tmp = 0x10000 | interrupt_coalescing; |
479 | mw32(MVS_INT_COAL_TMOUT, tmp); | 479 | mw32(MVS_INT_COAL_TMOUT, tmp); |
480 | 480 | ||
481 | /* ladies and gentlemen, start your engines */ | 481 | /* ladies and gentlemen, start your engines */ |
@@ -894,6 +894,29 @@ static void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, | |||
894 | { | 894 | { |
895 | } | 895 | } |
896 | 896 | ||
897 | static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time) | ||
898 | { | ||
899 | void __iomem *regs = mvi->regs; | ||
900 | u32 tmp = 0; | ||
901 | /* interrupt coalescing may cause missing HW interrput in some case, | ||
902 | * and the max count is 0x1ff, while our max slot is 0x200, | ||
903 | * it will make count 0. | ||
904 | */ | ||
905 | if (time == 0) { | ||
906 | mw32(MVS_INT_COAL, 0); | ||
907 | mw32(MVS_INT_COAL_TMOUT, 0x10000); | ||
908 | } else { | ||
909 | if (MVS_CHIP_SLOT_SZ > 0x1ff) | ||
910 | mw32(MVS_INT_COAL, 0x1ff|COAL_EN); | ||
911 | else | ||
912 | mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN); | ||
913 | |||
914 | tmp = 0x10000 | time; | ||
915 | mw32(MVS_INT_COAL_TMOUT, tmp); | ||
916 | } | ||
917 | |||
918 | } | ||
919 | |||
897 | const struct mvs_dispatch mvs_94xx_dispatch = { | 920 | const struct mvs_dispatch mvs_94xx_dispatch = { |
898 | "mv94xx", | 921 | "mv94xx", |
899 | mvs_94xx_init, | 922 | mvs_94xx_init, |
@@ -947,6 +970,7 @@ const struct mvs_dispatch mvs_94xx_dispatch = { | |||
947 | #ifndef DISABLE_HOTPLUG_DMA_FIX | 970 | #ifndef DISABLE_HOTPLUG_DMA_FIX |
948 | mvs_94xx_fix_dma, | 971 | mvs_94xx_fix_dma, |
949 | #endif | 972 | #endif |
973 | mvs_94xx_tune_interrupt, | ||
950 | mvs_94xx_non_spec_ncq_error, | 974 | mvs_94xx_non_spec_ncq_error, |
951 | }; | 975 | }; |
952 | 976 | ||
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 9f1cccc2a3ed..531093ddc418 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c | |||
@@ -34,6 +34,8 @@ MODULE_PARM_DESC(collector, "\n" | |||
34 | "\tThe mvsas SAS LLDD supports both modes.\n" | 34 | "\tThe mvsas SAS LLDD supports both modes.\n" |
35 | "\tDefault: 1 (Direct Mode).\n"); | 35 | "\tDefault: 1 (Direct Mode).\n"); |
36 | 36 | ||
37 | int interrupt_coalescing = 0x80; | ||
38 | |||
37 | static struct scsi_transport_template *mvs_stt; | 39 | static struct scsi_transport_template *mvs_stt; |
38 | struct kmem_cache *mvs_task_list_cache; | 40 | struct kmem_cache *mvs_task_list_cache; |
39 | static const struct mvs_chip_info mvs_chips[] = { | 41 | static const struct mvs_chip_info mvs_chips[] = { |
@@ -48,6 +50,8 @@ static const struct mvs_chip_info mvs_chips[] = { | |||
48 | [chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, | 50 | [chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, |
49 | }; | 51 | }; |
50 | 52 | ||
53 | struct device_attribute *mvst_host_attrs[]; | ||
54 | |||
51 | #define SOC_SAS_NUM 2 | 55 | #define SOC_SAS_NUM 2 |
52 | #define SG_MX 64 | 56 | #define SG_MX 64 |
53 | 57 | ||
@@ -74,6 +78,7 @@ static struct scsi_host_template mvs_sht = { | |||
74 | .slave_alloc = mvs_slave_alloc, | 78 | .slave_alloc = mvs_slave_alloc, |
75 | .target_destroy = sas_target_destroy, | 79 | .target_destroy = sas_target_destroy, |
76 | .ioctl = sas_ioctl, | 80 | .ioctl = sas_ioctl, |
81 | .shost_attrs = mvst_host_attrs, | ||
77 | }; | 82 | }; |
78 | 83 | ||
79 | static struct sas_domain_function_template mvs_transport_ops = { | 84 | static struct sas_domain_function_template mvs_transport_ops = { |
@@ -706,6 +711,70 @@ static struct pci_driver mvs_pci_driver = { | |||
706 | .remove = __devexit_p(mvs_pci_remove), | 711 | .remove = __devexit_p(mvs_pci_remove), |
707 | }; | 712 | }; |
708 | 713 | ||
714 | static ssize_t | ||
715 | mvs_show_driver_version(struct device *cdev, | ||
716 | struct device_attribute *attr, char *buffer) | ||
717 | { | ||
718 | return snprintf(buffer, PAGE_SIZE, "%s\n", DRV_VERSION); | ||
719 | } | ||
720 | |||
721 | static DEVICE_ATTR(driver_version, | ||
722 | S_IRUGO, | ||
723 | mvs_show_driver_version, | ||
724 | NULL); | ||
725 | |||
726 | static ssize_t | ||
727 | mvs_store_interrupt_coalescing(struct device *cdev, | ||
728 | struct device_attribute *attr, | ||
729 | const char *buffer, size_t size) | ||
730 | { | ||
731 | int val = 0; | ||
732 | struct mvs_info *mvi = NULL; | ||
733 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
734 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
735 | u8 i, core_nr; | ||
736 | if (buffer == NULL) | ||
737 | return size; | ||
738 | |||
739 | if (sscanf(buffer, "%d", &val) != 1) | ||
740 | return -EINVAL; | ||
741 | |||
742 | if (val >= 0x10000) { | ||
743 | mv_dprintk("interrupt coalescing timer %d us is" | ||
744 | "too long\n", val); | ||
745 | return strlen(buffer); | ||
746 | } | ||
747 | |||
748 | interrupt_coalescing = val; | ||
749 | |||
750 | core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; | ||
751 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; | ||
752 | |||
753 | if (unlikely(!mvi)) | ||
754 | return -EINVAL; | ||
755 | |||
756 | for (i = 0; i < core_nr; i++) { | ||
757 | mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; | ||
758 | if (MVS_CHIP_DISP->tune_interrupt) | ||
759 | MVS_CHIP_DISP->tune_interrupt(mvi, | ||
760 | interrupt_coalescing); | ||
761 | } | ||
762 | mv_dprintk("set interrupt coalescing time to %d us\n", | ||
763 | interrupt_coalescing); | ||
764 | return strlen(buffer); | ||
765 | } | ||
766 | |||
767 | static ssize_t mvs_show_interrupt_coalescing(struct device *cdev, | ||
768 | struct device_attribute *attr, char *buffer) | ||
769 | { | ||
770 | return snprintf(buffer, PAGE_SIZE, "%d\n", interrupt_coalescing); | ||
771 | } | ||
772 | |||
773 | static DEVICE_ATTR(interrupt_coalescing, | ||
774 | S_IRUGO|S_IWUSR, | ||
775 | mvs_show_interrupt_coalescing, | ||
776 | mvs_store_interrupt_coalescing); | ||
777 | |||
709 | /* task handler */ | 778 | /* task handler */ |
710 | struct task_struct *mvs_th; | 779 | struct task_struct *mvs_th; |
711 | static int __init mvs_init(void) | 780 | static int __init mvs_init(void) |
@@ -742,6 +811,12 @@ static void __exit mvs_exit(void) | |||
742 | kmem_cache_destroy(mvs_task_list_cache); | 811 | kmem_cache_destroy(mvs_task_list_cache); |
743 | } | 812 | } |
744 | 813 | ||
814 | struct device_attribute *mvst_host_attrs[] = { | ||
815 | &dev_attr_driver_version, | ||
816 | &dev_attr_interrupt_coalescing, | ||
817 | NULL, | ||
818 | }; | ||
819 | |||
745 | module_init(mvs_init); | 820 | module_init(mvs_init); |
746 | module_exit(mvs_exit); | 821 | module_exit(mvs_exit); |
747 | 822 | ||
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index ccd622f7f841..089ef1ef3865 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h | |||
@@ -64,6 +64,7 @@ | |||
64 | #endif | 64 | #endif |
65 | #define MV_MAX_U32 0xffffffff | 65 | #define MV_MAX_U32 0xffffffff |
66 | 66 | ||
67 | extern int interrupt_coalescing; | ||
67 | extern struct mvs_tgt_initiator mvs_tgt; | 68 | extern struct mvs_tgt_initiator mvs_tgt; |
68 | extern struct mvs_info *tgt_mvi; | 69 | extern struct mvs_info *tgt_mvi; |
69 | extern const struct mvs_dispatch mvs_64xx_dispatch; | 70 | extern const struct mvs_dispatch mvs_64xx_dispatch; |
@@ -170,6 +171,7 @@ struct mvs_dispatch { | |||
170 | #ifndef DISABLE_HOTPLUG_DMA_FIX | 171 | #ifndef DISABLE_HOTPLUG_DMA_FIX |
171 | void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd); | 172 | void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd); |
172 | #endif | 173 | #endif |
174 | void (*tune_interrupt)(struct mvs_info *mvi, u32 time); | ||
173 | void (*non_spec_ncq_error)(struct mvs_info *mvi); | 175 | void (*non_spec_ncq_error)(struct mvs_info *mvi); |
174 | 176 | ||
175 | }; | 177 | }; |