net/ionic: support notify queue
[dpdk.git] / drivers / net / ionic / ionic_ethdev.c
index f58d2d3..5719501 100644 (file)
@@ -31,6 +31,30 @@ static const struct rte_pci_id pci_id_ionic_map[] = {
 static const struct eth_dev_ops ionic_eth_dev_ops = {
 };
 
+/**
+ * Interrupt handler triggered by NIC for handling
+ * specific interrupt.
+ *
+ * @param param
+ *  The address of parameter registered before.
+ *
+ * @return
+ *  void
+ */
+static void
+ionic_dev_interrupt_handler(void *param)
+{
+       struct ionic_adapter *adapter = (struct ionic_adapter *)param;
+       uint32_t i;
+
+       IONIC_PRINT(DEBUG, "->");
+
+       for (i = 0; i < adapter->nlifs; i++) {
+               if (adapter->lifs[i])
+                       ionic_notifyq_handler(adapter->lifs[i], -1);
+       }
+}
+
 static int
 eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params)
 {
@@ -98,6 +122,70 @@ eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev)
        return 0;
 }
 
+static int
+ionic_configure_intr(struct ionic_adapter *adapter)
+{
+       struct rte_pci_device *pci_dev = adapter->pci_dev;
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+       int err;
+
+       IONIC_PRINT(DEBUG, "Configuring %u intrs", adapter->nintrs);
+
+       if (rte_intr_efd_enable(intr_handle, adapter->nintrs)) {
+               IONIC_PRINT(ERR, "Fail to create eventfd");
+               return -1;
+       }
+
+       if (rte_intr_dp_is_en(intr_handle))
+               IONIC_PRINT(DEBUG,
+                       "Packet I/O interrupt on datapath is enabled");
+
+       if (!intr_handle->intr_vec) {
+               intr_handle->intr_vec = rte_zmalloc("intr_vec",
+                       adapter->nintrs * sizeof(int), 0);
+
+               if (!intr_handle->intr_vec) {
+                       IONIC_PRINT(ERR, "Failed to allocate %u vectors",
+                               adapter->nintrs);
+                       return -ENOMEM;
+               }
+       }
+
+       err = rte_intr_callback_register(intr_handle,
+               ionic_dev_interrupt_handler,
+               adapter);
+
+       if (err) {
+               IONIC_PRINT(ERR,
+                       "Failure registering interrupts handler (%d)",
+                       err);
+               return err;
+       }
+
+       /* enable intr mapping */
+       err = rte_intr_enable(intr_handle);
+
+       if (err) {
+               IONIC_PRINT(ERR, "Failure enabling interrupts (%d)", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static void
+ionic_unconfigure_intr(struct ionic_adapter *adapter)
+{
+       struct rte_pci_device *pci_dev = adapter->pci_dev;
+       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+
+       rte_intr_disable(intr_handle);
+
+       rte_intr_callback_unregister(intr_handle,
+               ionic_dev_interrupt_handler,
+               adapter);
+}
+
 static int
 eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
                struct rte_pci_device *pci_dev)
@@ -221,6 +309,13 @@ eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
                adapter->nlifs++;
        }
 
+       err = ionic_configure_intr(adapter);
+
+       if (err) {
+               IONIC_PRINT(ERR, "Failed to configure interrupts");
+               goto err_free_adapter;
+       }
+
        return 0;
 
 err_free_adapter:
@@ -249,6 +344,8 @@ eth_ionic_pci_remove(struct rte_pci_device *pci_dev __rte_unused)
        }
 
        if (adapter) {
+               ionic_unconfigure_intr(adapter);
+
                for (i = 0; i < adapter->nlifs; i++) {
                        lif = adapter->lifs[i];
                        rte_eth_dev_destroy(lif->eth_dev, eth_ionic_dev_uninit);