Skip to content

Commit f05a0d8

Browse files
77liuqigregkh
authored andcommitted
scsi: hisi_sas: Free irq vectors in order for v3 HW
[ Upstream commit 554fb72 ] If the driver probe fails to request the channel IRQ or fatal IRQ, the driver will free the IRQ vectors before freeing the IRQs in free_irq(), and this will cause a kernel BUG like this: ------------[ cut here ]------------ kernel BUG at drivers/pci/msi.c:369! Internal error: Oops - BUG: 0 [#1] PREEMPT SMP Call trace: free_msi_irqs+0x118/0x13c pci_disable_msi+0xfc/0x120 pci_free_irq_vectors+0x24/0x3c hisi_sas_v3_probe+0x360/0x9d0 [hisi_sas_v3_hw] local_pci_probe+0x44/0xb0 work_for_cpu_fn+0x20/0x34 process_one_work+0x1d0/0x340 worker_thread+0x2e0/0x460 kthread+0x180/0x190 ret_from_fork+0x10/0x20 ---[ end trace b88990335b610c11 ]--- So we use devm_add_action() to control the order in which we free the vectors. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Qi Liu <[email protected]> Signed-off-by: John Garry <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent b8fa10d commit f05a0d8

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2392,17 +2392,25 @@ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
23922392
return IRQ_WAKE_THREAD;
23932393
}
23942394

2395+
static void hisi_sas_v3_free_vectors(void *data)
2396+
{
2397+
struct pci_dev *pdev = data;
2398+
2399+
pci_free_irq_vectors(pdev);
2400+
}
2401+
23952402
static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
23962403
{
23972404
int vectors;
23982405
int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi;
23992406
struct Scsi_Host *shost = hisi_hba->shost;
2407+
struct pci_dev *pdev = hisi_hba->pci_dev;
24002408
struct irq_affinity desc = {
24012409
.pre_vectors = BASE_VECTORS_V3_HW,
24022410
};
24032411

24042412
min_msi = MIN_AFFINE_VECTORS_V3_HW;
2405-
vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev,
2413+
vectors = pci_alloc_irq_vectors_affinity(pdev,
24062414
min_msi, max_msi,
24072415
PCI_IRQ_MSI |
24082416
PCI_IRQ_AFFINITY,
@@ -2414,6 +2422,7 @@ static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
24142422
hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW;
24152423
shost->nr_hw_queues = hisi_hba->cq_nvecs;
24162424

2425+
devm_add_action(&pdev->dev, hisi_sas_v3_free_vectors, pdev);
24172426
return 0;
24182427
}
24192428

@@ -4763,7 +4772,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
47634772
dev_err(dev, "%d hw queues\n", shost->nr_hw_queues);
47644773
rc = scsi_add_host(shost, dev);
47654774
if (rc)
4766-
goto err_out_free_irq_vectors;
4775+
goto err_out_debugfs;
47674776

47684777
rc = sas_register_ha(sha);
47694778
if (rc)
@@ -4792,8 +4801,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
47924801
sas_unregister_ha(sha);
47934802
err_out_register_ha:
47944803
scsi_remove_host(shost);
4795-
err_out_free_irq_vectors:
4796-
pci_free_irq_vectors(pdev);
47974804
err_out_debugfs:
47984805
debugfs_exit_v3_hw(hisi_hba);
47994806
err_out_ha:
@@ -4821,7 +4828,6 @@ hisi_sas_v3_destroy_irqs(struct pci_dev *pdev, struct hisi_hba *hisi_hba)
48214828

48224829
devm_free_irq(&pdev->dev, pci_irq_vector(pdev, nr), cq);
48234830
}
4824-
pci_free_irq_vectors(pdev);
48254831
}
48264832

48274833
static void hisi_sas_v3_remove(struct pci_dev *pdev)

0 commit comments

Comments
 (0)