aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2014-01-15 07:30:53 -0500
committerJames Bottomley <JBottomley@Parallels.com>2014-03-15 13:19:01 -0400
commiteee0f03a547f50ca81a8d01ee9f1c84fecd1f64c (patch)
tree16458ace56ca4a5b5557d0d36b23d39810181828
parent6e40e5f021d9f322342f3757d092431ed8c6b6d8 (diff)
[SCSI] hpsa: fixup MSI-X registration
Commit 254f796b9f22b1944c64caabc356a56caaa2facd updated the driver to use 16 MSI-X vectors, despite the fact that older controllers would provide only 4. This was causing MSI-X registration to drop down to INTx mode. But as the controller support performant mode, the initialisation will become confused and cause the machine to stall during boot. This patch fixes up the MSI-X registration to re-issue the pci_enable_msix() call with the correct number of MSI-X vectors. With that the hpsa driver continues to works on older controllers like the P200. Signed-off-by: Hannes Reinecke <hare@suse.de> Acked-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/hpsa.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 868318a7067c..40989eea8f97 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -598,7 +598,7 @@ static void set_performant_mode(struct ctlr_info *h, struct CommandList *c)
598{ 598{
599 if (likely(h->transMethod & CFGTBL_Trans_Performant)) { 599 if (likely(h->transMethod & CFGTBL_Trans_Performant)) {
600 c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); 600 c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
601 if (likely(h->msix_vector)) 601 if (likely(h->msix_vector > 0))
602 c->Header.ReplyQueue = 602 c->Header.ReplyQueue =
603 raw_smp_processor_id() % h->nreply_queues; 603 raw_smp_processor_id() % h->nreply_queues;
604 } 604 }
@@ -4169,21 +4169,24 @@ static void hpsa_interrupt_mode(struct ctlr_info *h)
4169 goto default_int_mode; 4169 goto default_int_mode;
4170 if (pci_find_capability(h->pdev, PCI_CAP_ID_MSIX)) { 4170 if (pci_find_capability(h->pdev, PCI_CAP_ID_MSIX)) {
4171 dev_info(&h->pdev->dev, "MSIX\n"); 4171 dev_info(&h->pdev->dev, "MSIX\n");
4172 h->msix_vector = MAX_REPLY_QUEUES;
4172 err = pci_enable_msix(h->pdev, hpsa_msix_entries, 4173 err = pci_enable_msix(h->pdev, hpsa_msix_entries,
4173 MAX_REPLY_QUEUES); 4174 h->msix_vector);
4174 if (!err) {
4175 for (i = 0; i < MAX_REPLY_QUEUES; i++)
4176 h->intr[i] = hpsa_msix_entries[i].vector;
4177 h->msix_vector = 1;
4178 return;
4179 }
4180 if (err > 0) { 4175 if (err > 0) {
4181 dev_warn(&h->pdev->dev, "only %d MSI-X vectors " 4176 dev_warn(&h->pdev->dev, "only %d MSI-X vectors "
4182 "available\n", err); 4177 "available\n", err);
4183 goto default_int_mode; 4178 h->msix_vector = err;
4179 err = pci_enable_msix(h->pdev, hpsa_msix_entries,
4180 h->msix_vector);
4181 }
4182 if (!err) {
4183 for (i = 0; i < h->msix_vector; i++)
4184 h->intr[i] = hpsa_msix_entries[i].vector;
4185 return;
4184 } else { 4186 } else {
4185 dev_warn(&h->pdev->dev, "MSI-X init failed %d\n", 4187 dev_warn(&h->pdev->dev, "MSI-X init failed %d\n",
4186 err); 4188 err);
4189 h->msix_vector = 0;
4187 goto default_int_mode; 4190 goto default_int_mode;
4188 } 4191 }
4189 } 4192 }
@@ -4597,15 +4600,15 @@ static int hpsa_request_irq(struct ctlr_info *h,
4597 for (i = 0; i < MAX_REPLY_QUEUES; i++) 4600 for (i = 0; i < MAX_REPLY_QUEUES; i++)
4598 h->q[i] = (u8) i; 4601 h->q[i] = (u8) i;
4599 4602
4600 if (h->intr_mode == PERF_MODE_INT && h->msix_vector) { 4603 if (h->intr_mode == PERF_MODE_INT && h->msix_vector > 0) {
4601 /* If performant mode and MSI-X, use multiple reply queues */ 4604 /* If performant mode and MSI-X, use multiple reply queues */
4602 for (i = 0; i < MAX_REPLY_QUEUES; i++) 4605 for (i = 0; i < h->msix_vector; i++)
4603 rc = request_irq(h->intr[i], msixhandler, 4606 rc = request_irq(h->intr[i], msixhandler,
4604 0, h->devname, 4607 0, h->devname,
4605 &h->q[i]); 4608 &h->q[i]);
4606 } else { 4609 } else {
4607 /* Use single reply pool */ 4610 /* Use single reply pool */
4608 if (h->msix_vector || h->msi_vector) { 4611 if (h->msix_vector > 0 || h->msi_vector) {
4609 rc = request_irq(h->intr[h->intr_mode], 4612 rc = request_irq(h->intr[h->intr_mode],
4610 msixhandler, 0, h->devname, 4613 msixhandler, 0, h->devname,
4611 &h->q[h->intr_mode]); 4614 &h->q[h->intr_mode]);
@@ -4658,7 +4661,7 @@ static void free_irqs(struct ctlr_info *h)
4658 return; 4661 return;
4659 } 4662 }
4660 4663
4661 for (i = 0; i < MAX_REPLY_QUEUES; i++) 4664 for (i = 0; i < h->msix_vector; i++)
4662 free_irq(h->intr[i], &h->q[i]); 4665 free_irq(h->intr[i], &h->q[i]);
4663} 4666}
4664 4667
@@ -5178,7 +5181,7 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
5178 if (!(trans_support & PERFORMANT_MODE)) 5181 if (!(trans_support & PERFORMANT_MODE))
5179 return; 5182 return;
5180 5183
5181 h->nreply_queues = h->msix_vector ? MAX_REPLY_QUEUES : 1; 5184 h->nreply_queues = h->msix_vector > 0 ? h->msix_vector : 1;
5182 hpsa_get_max_perf_mode_cmds(h); 5185 hpsa_get_max_perf_mode_cmds(h);
5183 /* Performant mode ring buffer and supporting data structures */ 5186 /* Performant mode ring buffer and supporting data structures */
5184 h->reply_pool_size = h->max_commands * sizeof(u64) * h->nreply_queues; 5187 h->reply_pool_size = h->max_commands * sizeof(u64) * h->nreply_queues;