1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00
corundum/modules/mqnic/mqnic_irq.c

122 lines
2.4 KiB
C
Raw Permalink Normal View History

2021-12-12 13:34:33 -08:00
// SPDX-License-Identifier: BSD-2-Clause-Views
/*
* Copyright (c) 2021-2023 The Regents of the University of California
2021-12-12 13:34:33 -08:00
*/
#include "mqnic.h"
static irqreturn_t mqnic_irq_handler(int irqn, void *data)
{
struct mqnic_irq *irq = data;
atomic_notifier_call_chain(&irq->nh, 0, NULL);
return IRQ_HANDLED;
}
int mqnic_irq_init_pcie(struct mqnic_dev *mdev)
{
struct pci_dev *pdev = mdev->pdev;
struct device *dev = mdev->dev;
int ret = 0;
int k;
// Allocate MSI IRQs
mdev->irq_count = pci_alloc_irq_vectors(pdev, 1, MQNIC_MAX_IRQ, PCI_IRQ_MSI | PCI_IRQ_MSIX);
2021-12-12 13:34:33 -08:00
if (mdev->irq_count < 0) {
dev_err(dev, "Failed to allocate IRQs");
return -ENOMEM;
}
// Set up interrupts
for (k = 0; k < mdev->irq_count; k++) {
struct mqnic_irq *irq;
irq = kzalloc(sizeof(*irq), GFP_KERNEL);
if (!irq) {
ret = -ENOMEM;
goto fail;
}
ATOMIC_INIT_NOTIFIER_HEAD(&irq->nh);
ret = pci_request_irq(pdev, k, mqnic_irq_handler, NULL,
irq, "%s-%d", mdev->name, k);
if (ret < 0) {
kfree(irq);
ret = -ENOMEM;
dev_err(dev, "Failed to request IRQ %d", k);
goto fail;
}
irq->index = k;
irq->irqn = pci_irq_vector(pdev, k);
mdev->irq[k] = irq;
}
dev_info(dev, "Configured %d IRQs", mdev->irq_count);
2021-12-12 13:34:33 -08:00
return 0;
fail:
mqnic_irq_deinit_pcie(mdev);
return ret;
}
void mqnic_irq_deinit_pcie(struct mqnic_dev *mdev)
{
struct pci_dev *pdev = mdev->pdev;
int k;
for (k = 0; k < MQNIC_MAX_IRQ; k++) {
if (mdev->irq[k]) {
pci_free_irq(pdev, k, mdev->irq[k]);
kfree(mdev->irq[k]);
mdev->irq[k] = NULL;
}
}
pci_free_irq_vectors(pdev);
}
int mqnic_irq_init_platform(struct mqnic_dev *mdev)
{
struct platform_device *pdev = mdev->pfdev;
struct device *dev = mdev->dev;
int k;
// Allocate IRQs
mdev->irq_count = platform_irq_count(pdev);
// Set up interrupts
for (k = 0; k < mdev->irq_count; k++) {
int irqn;
struct mqnic_irq *irq;
int ret;
irqn = platform_get_irq(pdev, k);
if (irqn < 0)
return irqn;
irq = devm_kzalloc(dev, sizeof(*irq), GFP_KERNEL);
if (!irq)
return -ENOMEM;
ATOMIC_INIT_NOTIFIER_HEAD(&irq->nh);
snprintf(irq->name, sizeof(irq->name), "%s-%u", mdev->name, k);
ret = devm_request_irq(dev, irqn, mqnic_irq_handler, 0, irq->name, irq);
if (ret < 0) {
dev_err(dev, "Failed to request IRQ %d (interrupt number %d)", k, irqn);
return ret;
}
irq->index = k;
irq->irqn = irqn;
mdev->irq[k] = irq;
}
dev_info(dev, "Configured %d IRQs", mdev->irq_count);
return 0;
}