From ddeb8bad9478fda8e27cb904990f828b9f153648 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 10 Dec 2021 21:05:31 -0800 Subject: [PATCH] Use atomic notifier chain for interrupt handling --- modules/mqnic/mqnic.h | 3 ++- modules/mqnic/mqnic_eq.c | 30 +++++++++++++++++++++++++++++- modules/mqnic/mqnic_hw.h | 2 ++ modules/mqnic/mqnic_main.c | 35 +++++++++-------------------------- modules/mqnic/mqnic_netdev.c | 1 - 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/modules/mqnic/mqnic.h b/modules/mqnic/mqnic.h index a6c1d2eb5..01d1736d0 100644 --- a/modules/mqnic/mqnic.h +++ b/modules/mqnic/mqnic.h @@ -104,6 +104,7 @@ struct mqnic_dev { int irq_count; int irq_map[32]; + struct atomic_notifier_head irq_nh[MQNIC_MAX_IRQ]; unsigned int id; struct list_head dev_list_node; @@ -255,7 +256,7 @@ struct mqnic_eq_ring { int int_index; int active; - int irq; + struct notifier_block irq_nb; void (*handler)(struct mqnic_eq_ring *ring); diff --git a/modules/mqnic/mqnic_eq.c b/modules/mqnic/mqnic_eq.c index 4fd6b99d0..9b9446c75 100644 --- a/modules/mqnic/mqnic_eq.c +++ b/modules/mqnic/mqnic_eq.c @@ -35,6 +35,16 @@ #include "mqnic.h" +static int mqnic_eq_int(struct notifier_block *nb, unsigned long action, void *data) +{ + struct mqnic_eq_ring *ring = container_of(nb, struct mqnic_eq_ring, irq_nb); + + mqnic_process_eq(ring); + mqnic_arm_eq(ring); + + return NOTIFY_DONE; +} + int mqnic_create_eq_ring(struct mqnic_priv *priv, struct mqnic_eq_ring **ring_ptr, int size, int stride, int index, u8 __iomem *hw_addr) { @@ -52,6 +62,8 @@ int mqnic_create_eq_ring(struct mqnic_priv *priv, struct mqnic_eq_ring **ring_pt ring->ring_index = index; ring->active = 0; + ring->irq_nb.notifier_call = mqnic_eq_int; + ring->size = roundup_pow_of_two(size); ring->size_mask = ring->size - 1; ring->stride = roundup_pow_of_two(stride); @@ -111,10 +123,20 @@ void mqnic_destroy_eq_ring(struct mqnic_eq_ring **ring_ptr) int mqnic_activate_eq_ring(struct mqnic_eq_ring *ring, int int_index) { + int ret = 0; + if (ring->active) mqnic_deactivate_eq_ring(ring); + if (int_index < 0 || int_index >= ring->priv->mdev->irq_count) + return -EINVAL; + + // register interrupt ring->int_index = int_index; + ret = atomic_notifier_chain_register(&ring->priv->mdev->irq_nh[int_index], &ring->irq_nb); + + if (ret) + return ret; // deactivate queue iowrite32(0, ring->hw_addr + MQNIC_EVENT_QUEUE_ACTIVE_LOG_SIZE_REG); @@ -134,16 +156,22 @@ int mqnic_activate_eq_ring(struct mqnic_eq_ring *ring, int int_index) ring->active = 1; - return 0; + return ret; } void mqnic_deactivate_eq_ring(struct mqnic_eq_ring *ring) { + int ret = 0; + // deactivate queue iowrite32(ilog2(ring->size), ring->hw_addr + MQNIC_EVENT_QUEUE_ACTIVE_LOG_SIZE_REG); // disarm queue iowrite32(ring->int_index, ring->hw_addr + MQNIC_EVENT_QUEUE_INTERRUPT_INDEX_REG); + // unregister interrupt + if (ring->active) + ret = atomic_notifier_chain_unregister(&ring->priv->mdev->irq_nh[ring->int_index], &ring->irq_nb); + ring->active = 0; } diff --git a/modules/mqnic/mqnic_hw.h b/modules/mqnic/mqnic_hw.h index b5682f620..38a076d6c 100644 --- a/modules/mqnic/mqnic_hw.h +++ b/modules/mqnic/mqnic_hw.h @@ -38,6 +38,8 @@ #include +#define MQNIC_MAX_IRQ 32 + #define MQNIC_MAX_IF 8 #define MQNIC_MAX_PORTS 8 #define MQNIC_MAX_SCHED 8 diff --git a/modules/mqnic/mqnic_main.c b/modules/mqnic/mqnic_main.c index b41cf99d4..2d859f2cd 100644 --- a/modules/mqnic/mqnic_main.c +++ b/modules/mqnic/mqnic_main.c @@ -80,30 +80,9 @@ static unsigned int mqnic_get_free_id(void) static irqreturn_t mqnic_interrupt(int irq, void *data) { - struct mqnic_dev *mqnic = data; - struct mqnic_priv *priv; + struct atomic_notifier_head *nh = data; - int k, l; - - for (k = 0; k < ARRAY_SIZE(mqnic->ndev); k++) { - if (unlikely(!mqnic->ndev[k])) - continue; - - priv = netdev_priv(mqnic->ndev[k]); - - if (unlikely(!priv->port_up)) - continue; - - for (l = 0; l < priv->event_queue_count; l++) { - if (unlikely(!priv->event_ring[l])) - continue; - - if (priv->event_ring[l]->irq == irq) { - mqnic_process_eq(priv->event_ring[l]); - mqnic_arm_eq(priv->event_ring[l]); - } - } - } + atomic_notifier_call_chain(nh, 0, NULL); return IRQ_HANDLED; } @@ -291,9 +270,13 @@ static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent } // Set up interrupts + for (k = 0; k < MQNIC_MAX_IRQ; k++) { + ATOMIC_INIT_NOTIFIER_HEAD(&mqnic->irq_nh[k]); + } + for (k = 0; k < mqnic->irq_count; k++) { ret = pci_request_irq(pdev, k, mqnic_interrupt, NULL, - mqnic, "%s-%d", mqnic->name, k); + &mqnic->irq_nh[k], "%s-%d", mqnic->name, k); if (ret < 0) { dev_err(dev, "Failed to request IRQ"); goto fail_irq; @@ -366,7 +349,7 @@ fail_init_netdev: fail_board: mqnic_board_deinit(mqnic); for (k = 0; k < mqnic->irq_count; k++) - pci_free_irq(pdev, k, mqnic); + pci_free_irq(pdev, k, &mqnic->irq_nh[k]); fail_irq: pci_free_irq_vectors(pdev); fail_map_bars: @@ -409,7 +392,7 @@ static void mqnic_pci_remove(struct pci_dev *pdev) pci_clear_master(pdev); mqnic_board_deinit(mqnic); for (k = 0; k < mqnic->irq_count; k++) - pci_free_irq(pdev, k, mqnic); + pci_free_irq(pdev, k, &mqnic->irq_nh[k]); pci_free_irq_vectors(pdev); if (mqnic->hw_addr) pci_iounmap(pdev, mqnic->hw_addr); diff --git a/modules/mqnic/mqnic_netdev.c b/modules/mqnic/mqnic_netdev.c index 76499d213..8e26d01ee 100644 --- a/modules/mqnic/mqnic_netdev.c +++ b/modules/mqnic/mqnic_netdev.c @@ -45,7 +45,6 @@ static int mqnic_start_port(struct net_device *ndev) // set up event queues for (k = 0; k < priv->event_queue_count; k++) { - priv->event_ring[k]->irq = mdev->irq_map[k % mdev->irq_count]; mqnic_activate_eq_ring(priv->event_ring[k], k % mdev->irq_count); mqnic_arm_eq(priv->event_ring[k]); }