lkml.org 
[lkml]   [2022]   [Apr]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 076/277] scsi: hisi_sas: Free irq vectors in order for v3 HW
    Date
    From: Qi Liu <liuqi115@huawei.com>

    [ Upstream commit 554fb72ee34f4732c7f694f56c3c6e67790352a0 ]

    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/1645703489-87194-4-git-send-email-john.garry@huawei.com
    Signed-off-by: Qi Liu <liuqi115@huawei.com>
    Signed-off-by: John Garry <john.garry@huawei.com>
    Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 16 +++++++++++-----
    1 file changed, 11 insertions(+), 5 deletions(-)

    diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
    index 1942970f9eb7..6010acae4cf3 100644
    --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
    +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
    @@ -2392,17 +2392,25 @@ static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
    return IRQ_WAKE_THREAD;
    }

    +static void hisi_sas_v3_free_vectors(void *data)
    +{
    + struct pci_dev *pdev = data;
    +
    + pci_free_irq_vectors(pdev);
    +}
    +
    static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
    {
    int vectors;
    int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi;
    struct Scsi_Host *shost = hisi_hba->shost;
    + struct pci_dev *pdev = hisi_hba->pci_dev;
    struct irq_affinity desc = {
    .pre_vectors = BASE_VECTORS_V3_HW,
    };

    min_msi = MIN_AFFINE_VECTORS_V3_HW;
    - vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev,
    + vectors = pci_alloc_irq_vectors_affinity(pdev,
    min_msi, max_msi,
    PCI_IRQ_MSI |
    PCI_IRQ_AFFINITY,
    @@ -2414,6 +2422,7 @@ static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
    hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW;
    shost->nr_hw_queues = hisi_hba->cq_nvecs;

    + devm_add_action(&pdev->dev, hisi_sas_v3_free_vectors, pdev);
    return 0;
    }

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

    rc = sas_register_ha(sha);
    if (rc)
    @@ -4792,8 +4801,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
    sas_unregister_ha(sha);
    err_out_register_ha:
    scsi_remove_host(shost);
    -err_out_free_irq_vectors:
    - pci_free_irq_vectors(pdev);
    err_out_debugfs:
    debugfs_exit_v3_hw(hisi_hba);
    err_out_ha:
    @@ -4821,7 +4828,6 @@ hisi_sas_v3_destroy_irqs(struct pci_dev *pdev, struct hisi_hba *hisi_hba)

    devm_free_irq(&pdev->dev, pci_irq_vector(pdev, nr), cq);
    }
    - pci_free_irq_vectors(pdev);
    }

    static void hisi_sas_v3_remove(struct pci_dev *pdev)
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-04-12 09:10    [W:3.509 / U:0.352 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site