diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2011-02-15 16:32:53 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-02-18 13:32:30 -0500 |
commit | a9a3a2739a44fc05dcaba0d4d36e52dc444c294f (patch) | |
tree | c43e58da09b90246f056a852ee698bc0028ac23f /drivers/scsi/hpsa.c | |
parent | 9e0fc764eaec082cd2ffcf82568dfdd086935934 (diff) |
[SCSI] hpsa: make hpsa.hpsa_simple_mode=1 module parameter actually work
It's not enough to simple avoid putting the board into performant
mode, as we have to set up the interrupts differently, etc. When
I originally tested this module parameter, I tested it incorrectly
without realizing it, and the driver was running in performant mode
the whole time unbeknownst to me.
Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r-- | drivers/scsi/hpsa.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0f40de2a33de..66ccacfffd51 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
@@ -1186,7 +1186,7 @@ static int hpsa_scsi_detect(struct ctlr_info *h) | |||
1186 | sh->sg_tablesize = h->maxsgentries; | 1186 | sh->sg_tablesize = h->maxsgentries; |
1187 | h->scsi_host = sh; | 1187 | h->scsi_host = sh; |
1188 | sh->hostdata[0] = (unsigned long) h; | 1188 | sh->hostdata[0] = (unsigned long) h; |
1189 | sh->irq = h->intr[PERF_MODE_INT]; | 1189 | sh->irq = h->intr[h->intr_mode]; |
1190 | sh->unique_id = sh->irq; | 1190 | sh->unique_id = sh->irq; |
1191 | error = scsi_add_host(sh, &h->pdev->dev); | 1191 | error = scsi_add_host(sh, &h->pdev->dev); |
1192 | if (error) | 1192 | if (error) |
@@ -2902,10 +2902,14 @@ static inline u32 hpsa_tag_to_index(u32 tag) | |||
2902 | return tag >> DIRECT_LOOKUP_SHIFT; | 2902 | return tag >> DIRECT_LOOKUP_SHIFT; |
2903 | } | 2903 | } |
2904 | 2904 | ||
2905 | static inline u32 hpsa_tag_discard_error_bits(u32 tag) | 2905 | |
2906 | static inline u32 hpsa_tag_discard_error_bits(struct ctlr_info *h, u32 tag) | ||
2906 | { | 2907 | { |
2907 | #define HPSA_ERROR_BITS 0x03 | 2908 | #define HPSA_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1) |
2908 | return tag & ~HPSA_ERROR_BITS; | 2909 | #define HPSA_SIMPLE_ERROR_BITS 0x03 |
2910 | if (unlikely(h->transMethod != CFGTBL_Trans_Performant)) | ||
2911 | return tag & ~HPSA_SIMPLE_ERROR_BITS; | ||
2912 | return tag & ~HPSA_PERF_ERROR_BITS; | ||
2909 | } | 2913 | } |
2910 | 2914 | ||
2911 | /* process completion of an indexed ("direct lookup") command */ | 2915 | /* process completion of an indexed ("direct lookup") command */ |
@@ -2930,7 +2934,7 @@ static inline u32 process_nonindexed_cmd(struct ctlr_info *h, | |||
2930 | u32 tag; | 2934 | u32 tag; |
2931 | struct CommandList *c = NULL; | 2935 | struct CommandList *c = NULL; |
2932 | 2936 | ||
2933 | tag = hpsa_tag_discard_error_bits(raw_tag); | 2937 | tag = hpsa_tag_discard_error_bits(h, raw_tag); |
2934 | list_for_each_entry(c, &h->cmpQ, list) { | 2938 | list_for_each_entry(c, &h->cmpQ, list) { |
2935 | if ((c->busaddr & 0xFFFFFFE0) == (tag & 0xFFFFFFE0)) { | 2939 | if ((c->busaddr & 0xFFFFFFE0) == (tag & 0xFFFFFFE0)) { |
2936 | finish_cmd(c, raw_tag); | 2940 | finish_cmd(c, raw_tag); |
@@ -2981,7 +2985,10 @@ static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id) | |||
2981 | return IRQ_HANDLED; | 2985 | return IRQ_HANDLED; |
2982 | } | 2986 | } |
2983 | 2987 | ||
2984 | /* Send a message CDB to the firmware. */ | 2988 | /* Send a message CDB to the firmware. Careful, this only works |
2989 | * in simple mode, not performant mode due to the tag lookup. | ||
2990 | * We only ever use this immediately after a controller reset. | ||
2991 | */ | ||
2985 | static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode, | 2992 | static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode, |
2986 | unsigned char type) | 2993 | unsigned char type) |
2987 | { | 2994 | { |
@@ -3047,7 +3054,7 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode, | |||
3047 | 3054 | ||
3048 | for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) { | 3055 | for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) { |
3049 | tag = readl(vaddr + SA5_REPLY_PORT_OFFSET); | 3056 | tag = readl(vaddr + SA5_REPLY_PORT_OFFSET); |
3050 | if (hpsa_tag_discard_error_bits(tag) == paddr32) | 3057 | if ((tag & ~HPSA_SIMPLE_ERROR_BITS) == paddr32) |
3051 | break; | 3058 | break; |
3052 | msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS); | 3059 | msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS); |
3053 | } | 3060 | } |
@@ -3379,7 +3386,7 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h) | |||
3379 | default_int_mode: | 3386 | default_int_mode: |
3380 | #endif /* CONFIG_PCI_MSI */ | 3387 | #endif /* CONFIG_PCI_MSI */ |
3381 | /* if we get here we're going to use the default interrupt mode */ | 3388 | /* if we get here we're going to use the default interrupt mode */ |
3382 | h->intr[PERF_MODE_INT] = h->pdev->irq; | 3389 | h->intr[h->intr_mode] = h->pdev->irq; |
3383 | } | 3390 | } |
3384 | 3391 | ||
3385 | static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id) | 3392 | static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id) |
@@ -3760,6 +3767,8 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, | |||
3760 | 3767 | ||
3761 | h->pdev = pdev; | 3768 | h->pdev = pdev; |
3762 | h->busy_initializing = 1; | 3769 | h->busy_initializing = 1; |
3770 | h->intr_mode = hpsa_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT; | ||
3771 | printk(KERN_WARNING "hpsa_simple_mode is %d\n", hpsa_simple_mode); | ||
3763 | INIT_LIST_HEAD(&h->cmpQ); | 3772 | INIT_LIST_HEAD(&h->cmpQ); |
3764 | INIT_LIST_HEAD(&h->reqQ); | 3773 | INIT_LIST_HEAD(&h->reqQ); |
3765 | spin_lock_init(&h->lock); | 3774 | spin_lock_init(&h->lock); |
@@ -3790,20 +3799,20 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, | |||
3790 | h->access.set_intr_mask(h, HPSA_INTR_OFF); | 3799 | h->access.set_intr_mask(h, HPSA_INTR_OFF); |
3791 | 3800 | ||
3792 | if (h->msix_vector || h->msi_vector) | 3801 | if (h->msix_vector || h->msi_vector) |
3793 | rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_msi, | 3802 | rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_msi, |
3794 | IRQF_DISABLED, h->devname, h); | 3803 | IRQF_DISABLED, h->devname, h); |
3795 | else | 3804 | else |
3796 | rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_intx, | 3805 | rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_intx, |
3797 | IRQF_DISABLED, h->devname, h); | 3806 | IRQF_DISABLED, h->devname, h); |
3798 | if (rc) { | 3807 | if (rc) { |
3799 | dev_err(&pdev->dev, "unable to get irq %d for %s\n", | 3808 | dev_err(&pdev->dev, "unable to get irq %d for %s\n", |
3800 | h->intr[PERF_MODE_INT], h->devname); | 3809 | h->intr[h->intr_mode], h->devname); |
3801 | goto clean2; | 3810 | goto clean2; |
3802 | } | 3811 | } |
3803 | 3812 | ||
3804 | dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n", | 3813 | dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n", |
3805 | h->devname, pdev->device, | 3814 | h->devname, pdev->device, |
3806 | h->intr[PERF_MODE_INT], dac ? "" : " not"); | 3815 | h->intr[h->intr_mode], dac ? "" : " not"); |
3807 | 3816 | ||
3808 | h->cmd_pool_bits = | 3817 | h->cmd_pool_bits = |
3809 | kmalloc(((h->nr_cmds + BITS_PER_LONG - | 3818 | kmalloc(((h->nr_cmds + BITS_PER_LONG - |
@@ -3854,7 +3863,7 @@ clean4: | |||
3854 | h->nr_cmds * sizeof(struct ErrorInfo), | 3863 | h->nr_cmds * sizeof(struct ErrorInfo), |
3855 | h->errinfo_pool, | 3864 | h->errinfo_pool, |
3856 | h->errinfo_pool_dhandle); | 3865 | h->errinfo_pool_dhandle); |
3857 | free_irq(h->intr[PERF_MODE_INT], h); | 3866 | free_irq(h->intr[h->intr_mode], h); |
3858 | clean2: | 3867 | clean2: |
3859 | clean1: | 3868 | clean1: |
3860 | h->busy_initializing = 0; | 3869 | h->busy_initializing = 0; |
@@ -3898,7 +3907,7 @@ static void hpsa_shutdown(struct pci_dev *pdev) | |||
3898 | */ | 3907 | */ |
3899 | hpsa_flush_cache(h); | 3908 | hpsa_flush_cache(h); |
3900 | h->access.set_intr_mask(h, HPSA_INTR_OFF); | 3909 | h->access.set_intr_mask(h, HPSA_INTR_OFF); |
3901 | free_irq(h->intr[PERF_MODE_INT], h); | 3910 | free_irq(h->intr[h->intr_mode], h); |
3902 | #ifdef CONFIG_PCI_MSI | 3911 | #ifdef CONFIG_PCI_MSI |
3903 | if (h->msix_vector) | 3912 | if (h->msix_vector) |
3904 | pci_disable_msix(h->pdev); | 3913 | pci_disable_msix(h->pdev); |