Skip to content

Commit 8b834bf

Browse files
Ming Leimartinkpetersen
authored andcommitted
scsi: hpsa: fix selection of reply queue
Since commit 84676c1 ("genirq/affinity: assign vectors to all possible CPUs") we could end up with an MSI-X vector that did not have any online CPUs mapped. This would lead to I/O hangs since there was no CPU to receive the completion. Retrieve IRQ affinity information using pci_irq_get_affinity() and use this mapping to choose a reply queue. [mkp: tweaked commit desc] Cc: Hannes Reinecke <hare@suse.de> Cc: "Martin K. Petersen" <martin.petersen@oracle.com>, Cc: James Bottomley <james.bottomley@hansenpartnership.com>, Cc: Christoph Hellwig <hch@lst.de>, Cc: Don Brace <don.brace@microsemi.com> Cc: Kashyap Desai <kashyap.desai@broadcom.com> Cc: Laurence Oberman <loberman@redhat.com> Cc: Meelis Roos <mroos@linux.ee> Cc: Artem Bityutskiy <artem.bityutskiy@intel.com> Cc: Mike Snitzer <snitzer@redhat.com> Fixes: 84676c1 ("genirq/affinity: assign vectors to all possible CPUs") Signed-off-by: Ming Lei <ming.lei@redhat.com> Tested-by: Laurence Oberman <loberman@redhat.com> Tested-by: Don Brace <don.brace@microsemi.com> Tested-by: Artem Bityutskiy <artem.bityutskiy@intel.com> Acked-by: Don Brace <don.brace@microsemi.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 14bc1df commit 8b834bf

File tree

2 files changed

+55
-19
lines changed

2 files changed

+55
-19
lines changed

drivers/scsi/hpsa.c

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,11 +1045,7 @@ static void set_performant_mode(struct ctlr_info *h, struct CommandList *c,
10451045
c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
10461046
if (unlikely(!h->msix_vectors))
10471047
return;
1048-
if (likely(reply_queue == DEFAULT_REPLY_QUEUE))
1049-
c->Header.ReplyQueue =
1050-
raw_smp_processor_id() % h->nreply_queues;
1051-
else
1052-
c->Header.ReplyQueue = reply_queue % h->nreply_queues;
1048+
c->Header.ReplyQueue = reply_queue;
10531049
}
10541050
}
10551051

@@ -1063,10 +1059,7 @@ static void set_ioaccel1_performant_mode(struct ctlr_info *h,
10631059
* Tell the controller to post the reply to the queue for this
10641060
* processor. This seems to give the best I/O throughput.
10651061
*/
1066-
if (likely(reply_queue == DEFAULT_REPLY_QUEUE))
1067-
cp->ReplyQueue = smp_processor_id() % h->nreply_queues;
1068-
else
1069-
cp->ReplyQueue = reply_queue % h->nreply_queues;
1062+
cp->ReplyQueue = reply_queue;
10701063
/*
10711064
* Set the bits in the address sent down to include:
10721065
* - performant mode bit (bit 0)
@@ -1087,10 +1080,7 @@ static void set_ioaccel2_tmf_performant_mode(struct ctlr_info *h,
10871080
/* Tell the controller to post the reply to the queue for this
10881081
* processor. This seems to give the best I/O throughput.
10891082
*/
1090-
if (likely(reply_queue == DEFAULT_REPLY_QUEUE))
1091-
cp->reply_queue = smp_processor_id() % h->nreply_queues;
1092-
else
1093-
cp->reply_queue = reply_queue % h->nreply_queues;
1083+
cp->reply_queue = reply_queue;
10941084
/* Set the bits in the address sent down to include:
10951085
* - performant mode bit not used in ioaccel mode 2
10961086
* - pull count (bits 0-3)
@@ -1109,10 +1099,7 @@ static void set_ioaccel2_performant_mode(struct ctlr_info *h,
11091099
* Tell the controller to post the reply to the queue for this
11101100
* processor. This seems to give the best I/O throughput.
11111101
*/
1112-
if (likely(reply_queue == DEFAULT_REPLY_QUEUE))
1113-
cp->reply_queue = smp_processor_id() % h->nreply_queues;
1114-
else
1115-
cp->reply_queue = reply_queue % h->nreply_queues;
1102+
cp->reply_queue = reply_queue;
11161103
/*
11171104
* Set the bits in the address sent down to include:
11181105
* - performant mode bit not used in ioaccel mode 2
@@ -1157,6 +1144,8 @@ static void __enqueue_cmd_and_start_io(struct ctlr_info *h,
11571144
{
11581145
dial_down_lockup_detection_during_fw_flash(h, c);
11591146
atomic_inc(&h->commands_outstanding);
1147+
1148+
reply_queue = h->reply_map[raw_smp_processor_id()];
11601149
switch (c->cmd_type) {
11611150
case CMD_IOACCEL1:
11621151
set_ioaccel1_performant_mode(h, c, reply_queue);
@@ -7376,6 +7365,26 @@ static void hpsa_disable_interrupt_mode(struct ctlr_info *h)
73767365
h->msix_vectors = 0;
73777366
}
73787367

7368+
static void hpsa_setup_reply_map(struct ctlr_info *h)
7369+
{
7370+
const struct cpumask *mask;
7371+
unsigned int queue, cpu;
7372+
7373+
for (queue = 0; queue < h->msix_vectors; queue++) {
7374+
mask = pci_irq_get_affinity(h->pdev, queue);
7375+
if (!mask)
7376+
goto fallback;
7377+
7378+
for_each_cpu(cpu, mask)
7379+
h->reply_map[cpu] = queue;
7380+
}
7381+
return;
7382+
7383+
fallback:
7384+
for_each_possible_cpu(cpu)
7385+
h->reply_map[cpu] = 0;
7386+
}
7387+
73797388
/* If MSI/MSI-X is supported by the kernel we will try to enable it on
73807389
* controllers that are capable. If not, we use legacy INTx mode.
73817390
*/
@@ -7771,6 +7780,10 @@ static int hpsa_pci_init(struct ctlr_info *h)
77717780
err = hpsa_interrupt_mode(h);
77727781
if (err)
77737782
goto clean1;
7783+
7784+
/* setup mapping between CPU and reply queue */
7785+
hpsa_setup_reply_map(h);
7786+
77747787
err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr);
77757788
if (err)
77767789
goto clean2; /* intmode+region, pci */
@@ -8480,6 +8493,28 @@ static struct workqueue_struct *hpsa_create_controller_wq(struct ctlr_info *h,
84808493
return wq;
84818494
}
84828495

8496+
static void hpda_free_ctlr_info(struct ctlr_info *h)
8497+
{
8498+
kfree(h->reply_map);
8499+
kfree(h);
8500+
}
8501+
8502+
static struct ctlr_info *hpda_alloc_ctlr_info(void)
8503+
{
8504+
struct ctlr_info *h;
8505+
8506+
h = kzalloc(sizeof(*h), GFP_KERNEL);
8507+
if (!h)
8508+
return NULL;
8509+
8510+
h->reply_map = kzalloc(sizeof(*h->reply_map) * nr_cpu_ids, GFP_KERNEL);
8511+
if (!h->reply_map) {
8512+
kfree(h);
8513+
return NULL;
8514+
}
8515+
return h;
8516+
}
8517+
84838518
static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
84848519
{
84858520
int dac, rc;
@@ -8517,7 +8552,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
85178552
* the driver. See comments in hpsa.h for more info.
85188553
*/
85198554
BUILD_BUG_ON(sizeof(struct CommandList) % COMMANDLIST_ALIGNMENT);
8520-
h = kzalloc(sizeof(*h), GFP_KERNEL);
8555+
h = hpda_alloc_ctlr_info();
85218556
if (!h) {
85228557
dev_err(&pdev->dev, "Failed to allocate controller head\n");
85238558
return -ENOMEM;
@@ -8916,7 +8951,7 @@ static void hpsa_remove_one(struct pci_dev *pdev)
89168951
h->lockup_detected = NULL; /* init_one 2 */
89178952
/* (void) pci_disable_pcie_error_reporting(pdev); */ /* init_one 1 */
89188953

8919-
kfree(h); /* init_one 1 */
8954+
hpda_free_ctlr_info(h); /* init_one 1 */
89208955
}
89218956

89228957
static int hpsa_suspend(__attribute__((unused)) struct pci_dev *pdev,

drivers/scsi/hpsa.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ struct bmic_controller_parameters {
158158
#pragma pack()
159159

160160
struct ctlr_info {
161+
unsigned int *reply_map;
161162
int ctlr;
162163
char devname[8];
163164
char *product_name;

0 commit comments

Comments
 (0)