From ecdb794504c3d7331077b9234194829db67030a5 Mon Sep 17 00:00:00 2001 From: Iman Seyed Date: Mon, 30 Sep 2024 12:52:01 -0400 Subject: [PATCH 1/3] snull: unlock priv if priv->ppool was NULL --- snull/snull.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/snull/snull.c b/snull/snull.c index 917ddec6c..fa9a2f73b 100644 --- a/snull/snull.c +++ b/snull/snull.c @@ -140,13 +140,15 @@ static struct snull_packet *snull_get_tx_buffer(struct net_device *dev) pkt = priv->ppool; if(!pkt) { PDEBUG("Out of Pool\n"); - return pkt; + goto out; } priv->ppool = pkt->next; if (priv->ppool == NULL) { printk (KERN_INFO "Pool empty\n"); netif_stop_queue(dev); } + +out: spin_unlock_irqrestore(&priv->lock, flags); return pkt; } From 1670c582aa2a111bc3240bd60cef7b4955bd0995 Mon Sep 17 00:00:00 2001 From: Iman Seyed Date: Sun, 6 Oct 2024 16:23:50 -0400 Subject: [PATCH 2/3] snull: fix error handling in device registeration If the first device registration fails, the second iteration of the loop will set the ret to zero. Also, jumping to snull_cleanup() will put the device into unreg queue which is unnecessary. --- snull/snull.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/snull/snull.c b/snull/snull.c index fa9a2f73b..328e2beb9 100644 --- a/snull/snull.c +++ b/snull/snull.c @@ -752,28 +752,29 @@ static void snull_cleanup(void) static int snull_init_module(void) { - int result, i, ret = -ENOMEM; + int result, i, ret = 0; snull_interrupt = use_napi ? snull_napi_interrupt : snull_regular_interrupt; - /* Allocate the devices */ - snull_devs[0] = alloc_netdev(sizeof(struct snull_priv), "sn%d", - NET_NAME_UNKNOWN, snull_init); - snull_devs[1] = alloc_netdev(sizeof(struct snull_priv), "sn%d", + /* Allocate and register the devices */ + for (i = 0; i < 2; i++) { + snull_devs[i] = alloc_netdev(sizeof(struct snull_priv), "sn%d", NET_NAME_UNKNOWN, snull_init); - if (snull_devs[0] == NULL || snull_devs[1] == NULL) - goto out; - ret = -ENODEV; - for (i = 0; i < 2; i++) - if ((result = register_netdev(snull_devs[i]))) + if (snull_devs[i] == NULL) { + ret = -ENOMEM; + break; + } + + if ((result = register_netdev(snull_devs[i]))) { printk("snull: error %i registering device \"%s\"\n", result, snull_devs[i]->name); - else - ret = 0; - out: - if (ret) - snull_cleanup(); + free_netdev(snull_devs[i]); + ret = -ENODEV; + break; + } + } + return ret; } From fbb575b4bc3750e4e050be646c5887a3a4a1ca34 Mon Sep 17 00:00:00 2001 From: Iman Seyed Date: Sun, 20 Oct 2024 03:02:58 -0400 Subject: [PATCH 3/3] snull: use napi_schedule_prep() to prevent packet loss By using napi_schedule_prep() and __napi_schedule(), ensure NAPI polls are scheduled before disabling interrupts. This prevents dropped polls and ensures rx_int_enabled is properly updated, fixing 100% packet loss during state changes. Authored-by: Leon Signed-off-by: Iman Seyed --- snull/snull.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snull/snull.c b/snull/snull.c index 328e2beb9..290d9d988 100644 --- a/snull/snull.c +++ b/snull/snull.c @@ -428,9 +428,9 @@ static void snull_napi_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* retrieve statusword: real netdevices use I/O instructions */ statusword = priv->status; priv->status = 0; - if (statusword & SNULL_RX_INTR) { + if (statusword & SNULL_RX_INTR && napi_schedule_prep(&priv->napi)) { snull_rx_ints(dev, 0); /* Disable further interrupts */ - napi_schedule(&priv->napi); + __napi_schedule(&priv->napi); } if (statusword & SNULL_TX_INTR) { /* a transmission is over: free the skb */