diff --git a/modules/mqnic/mqnic.h b/modules/mqnic/mqnic.h index b465cde1f..b44500722 100644 --- a/modules/mqnic/mqnic.h +++ b/modules/mqnic/mqnic.h @@ -77,6 +77,8 @@ struct mqnic_dev { char name[16]; + int msi_nvecs; + unsigned int id; struct list_head dev_list_node; @@ -201,6 +203,8 @@ struct mqnic_eq_ring { struct net_device *ndev; int int_index; + int irq; + void (*handler) (struct mqnic_eq_ring *); u32 hw_ptr_mask; diff --git a/modules/mqnic/mqnic_main.c b/modules/mqnic/mqnic_main.c index 77e0319b0..b0a327689 100644 --- a/modules/mqnic/mqnic_main.c +++ b/modules/mqnic/mqnic_main.c @@ -94,6 +94,39 @@ done: return mqnic; } +static irqreturn_t mqnic_interrupt(int irq, void *data) +{ + struct mqnic_dev *mqnic = data; + struct mqnic_priv *priv; + + int k, l; + + for (k = 0; k < MQNIC_MAX_IF; k++) + { + if (!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->ndev, priv->event_ring[l]); + mqnic_arm_eq(priv->event_ring[l]); + } + } + } + + return IRQ_HANDLED; +} + static int mqnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int ret = 0; @@ -203,13 +236,24 @@ static int mqnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(dev, "IF CSR offset: 0x%08x", mqnic->if_csr_offset); // Allocate MSI IRQs - ret = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); - if (ret < 0) + mqnic->msi_nvecs = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); + if (mqnic->msi_nvecs < 0) { dev_err(dev, "Failed to allocate IRQs"); goto fail_map_bars; } + // Set up interrupts + for (k = 0; k < mqnic->msi_nvecs; k++) + { + ret = pci_request_irq(pdev, k, mqnic_interrupt, 0, mqnic, "mqnic"); + if (ret < 0) + { + dev_err(dev, "Failed to request IRQ"); + goto fail_irq; + } + } + // Set up I2C interfaces ret = mqnic_init_i2c(mqnic); if (ret) @@ -285,6 +329,11 @@ fail_init_netdev: pci_clear_master(pdev); fail_i2c: mqnic_remove_i2c(mqnic); + for (k = 0; k < mqnic->msi_nvecs; k++) + { + pci_free_irq(pdev, k, mqnic); + } +fail_irq: pci_free_irq_vectors(pdev); fail_map_bars: pci_iounmap(pdev, mqnic->hw_addr); @@ -329,6 +378,10 @@ static void mqnic_remove(struct pci_dev *pdev) pci_clear_master(pdev); mqnic_remove_i2c(mqnic); + for (k = 0; k < mqnic->msi_nvecs; k++) + { + pci_free_irq(pdev, k, mqnic); + } pci_free_irq_vectors(pdev); pci_iounmap(pdev, mqnic->hw_addr); pci_release_regions(pdev); diff --git a/modules/mqnic/mqnic_netdev.c b/modules/mqnic/mqnic_netdev.c index 076ef494a..1b9ea7964 100644 --- a/modules/mqnic/mqnic_netdev.c +++ b/modules/mqnic/mqnic_netdev.c @@ -44,14 +44,15 @@ static int mqnic_open(struct net_device *ndev) // set up event queues for (k = 0; k < priv->event_queue_count; k++) { - mqnic_activate_eq_ring(priv, priv->event_ring[k], priv->port); // TODO interrupt index + priv->event_ring[k]->irq = pci_irq_vector(mdev->pdev, k % mdev->msi_nvecs); + mqnic_activate_eq_ring(priv, priv->event_ring[k], k % mdev->msi_nvecs); mqnic_arm_eq(priv->event_ring[k]); } // set up RX completion queues for (k = 0; k < priv->rx_cpl_queue_count; k++) { - mqnic_activate_cq_ring(priv, priv->rx_cpl_ring[k], 0); // TODO configure/constant + mqnic_activate_cq_ring(priv, priv->rx_cpl_ring[k], k % priv->event_queue_count); priv->rx_cpl_ring[k]->ring_index = k; priv->rx_cpl_ring[k]->handler = mqnic_rx_irq; @@ -70,7 +71,7 @@ static int mqnic_open(struct net_device *ndev) // set up TX completion queues for (k = 0; k < priv->tx_cpl_queue_count; k++) { - mqnic_activate_cq_ring(priv, priv->tx_cpl_ring[k], 0); // TODO configure/constant + mqnic_activate_cq_ring(priv, priv->tx_cpl_ring[k], k % priv->event_queue_count); priv->tx_cpl_ring[k]->ring_index = k; priv->tx_cpl_ring[k]->handler = mqnic_tx_irq; @@ -311,27 +312,6 @@ static const struct net_device_ops mqnic_netdev_ops = { .ndo_do_ioctl = mqnic_ioctl, }; -static irqreturn_t mqnic_netdev_interrupt(int irq, void *data) -{ - struct mqnic_priv *priv = data; - - int k; - - if (likely(priv->port_up)) - { - for (k = 0; k < priv->event_queue_count; k++) - { - if (likely(priv->event_ring[k])) - { - mqnic_process_eq(priv->ndev, priv->event_ring[k]); - mqnic_arm_eq(priv->event_ring[k]); - } - } - } - - return IRQ_HANDLED; -} - int mqnic_init_netdev(struct mqnic_dev *mdev, int port, u8 __iomem *hw_addr) { struct device *dev = &mdev->pdev->dev; @@ -421,15 +401,6 @@ int mqnic_init_netdev(struct mqnic_dev *mdev, int port, u8 __iomem *hw_addr) netif_set_real_num_tx_queues(ndev, priv->tx_queue_count); netif_set_real_num_rx_queues(ndev, priv->rx_queue_count); - // Set up interrupt - ret = pci_request_irq(mdev->pdev, priv->port, mqnic_netdev_interrupt, 0, priv, "mqnic%d", priv->port); - if (ret < 0) - { - dev_err(dev, "Failed to request IRQ"); - free_netdev(ndev); - return ret; - } - // set MAC ndev->addr_len = ETH_ALEN; memcpy(ndev->dev_addr, mdev->base_mac, ETH_ALEN); @@ -608,7 +579,6 @@ void mqnic_destroy_netdev(struct net_device *ndev) } } - pci_free_irq(mdev->pdev, priv->port, priv); free_netdev(ndev); }