Steps for phase one are as follows:
- Create header file
ena_netmap_linux.h
- Write function
ena_netmap_attach
- Patch https://github.com/amzn/amzn-drivers/blob/ena_linux_1.1.3/kernel/linux/ena/ena_netdev.c
ena_netmap_attach
netmap_detach
netmap_rx_irq
#include <bsd_glue.h>
#include <net/netmap.h>
#include <netmap/netmap_kern.h>
#ifdef NETMAP_LINUX_ENA_PTR_ARRAY
#define NM_ENA_TX_RING(a, r) ((a)->tx_rings[(r)])
#define NM_ENA_RX_RING(a, r) ((a)->rx_rings[(r)])
#else
#define NM_ENA_TX_RING(a, r) (&(a)->tx_rings[(r)])
#define NM_ENA_RX_RING(a, r) (&(a)->rx_rings[(r)])
#endif
/*
* The attach routine, called near the end of ena_probe(),
* fills the parameters for netmap_attach() and calls it.
* It cannot fail, in the worst case (such as no memory)
* netmap mode will be disabled and the driver will only
* operate in standard mode.
*/
static void
ena_netmap_attach(struct ena_adapter *adapter)
{
struct netmap_adapter na;
bzero(&na, sizeof(na));
na.ifp = adapter->netdev;
na.na_flags = NAF_BDG_MAYSLEEP;
na.pdev = &adapter->pdev->dev;
// XXX check that queues is set.
na.num_tx_desc = NM_ENA_TX_RING(adapter, 0)->count;
na.num_rx_desc = NM_ENA_RX_RING(adapter, 0)->count;
// na.nm_txsync = ena_netmap_txsync; // Task 3
// na.nm_rxsync = ena_netmap_rxsync; // Task 4
// na.nm_register = ena_netmap_reg; // Task 2
na.num_tx_rings = na.num_rx_rings = adapter->num_queue_pairs;
netmap_attach(&na);
}
Patch is to 1.1.3 tag of ena_netdev.c
diff --git a/ena_netdev.c b/ena_netdev.c
index 0facf46..445857b 100644
--- a/ena_netdev.c
+++ b/ena_netdev.c
@@ -54,6 +54,10 @@
#include "ena_pci_id_tbl.h"
#include "ena_sysfs.h"
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
+#include <ena_netmap.h>
+#endif
+
static char version[] = DEVICE_NAME " v" DRV_MODULE_VERSION "\n";
MODULE_AUTHOR("Amazon.com, Inc. or its affiliates");
@@ -696,6 +700,13 @@ static int ena_clean_tx_irq(struct ena_ring *tx_ring, u32 budget)
int tx_pkts = 0;
int rc;
+ struct ena_adapter *adapter = tx_ring->adapter;
+ struct net_device *netdev = adapter->netdev;
+#ifdef DEV_NETMAP
+ if (netmap_tx_irq(netdev, 0))
+ return true; /* cleaned ok */
+#endif /* DEV_NETMAP */
+
next_to_clean = tx_ring->next_to_clean;
txq = netdev_get_tx_queue(tx_ring->netdev, tx_ring->qid);
@@ -1013,6 +1024,18 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
int total_len = 0;
int rx_copybreak_pkt = 0;
+ struct net_device *netdev = adapter->netdev;
+#ifdef DEV_NETMAP
+#ifdef CONFIG_ENA_NAPI
+#define NETMAP_DUMMY work_done
+#else
+ int dummy;
+#define NETMAP_DUMMY &dummy
+#endif
+ if (netmap_rx_irq(netdev, 0, NETMAP_DUMMY))
+ return true;
+#endif /* DEV_NETMAP */
+
netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
"%s qid %d\n", __func__, rx_ring->qid);
res_budget = budget;
@@ -3377,6 +3400,10 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->timer_service.function = ena_timer_service;
adapter->timer_service.data = (unsigned long)adapter;
+#ifdef DEV_NETMAP
+ ena_netmap_attach(adapter);
+#endif /* DEV_NETMAP */
+
add_timer(&adapter->timer_service);
dev_info(&pdev->dev, "%s found at mem %lx, mac addr %pM Queues %d\n",
@@ -3517,6 +3544,11 @@ static void ena_remove(struct pci_dev *pdev)
ena_com_destroy_interrupt_moderation(ena_dev);
vfree(ena_dev);
+
+#ifdef DEV_NETMAP
+ netmap_detach(netdev);
+#endif /* DEV_NETMAP */
+
}
static struct pci_driver ena_pci_driver = {