Why Does the RTL8139 Driver Miss the First TCP SYN? A Deep Dive into ISR Handling

A developer discovers that clearing the entire ISR register in the RTL8139 driver masks a pending Rx interrupt, causing the first TCP SYN packet to be lost, and resolves the issue by clearing only the TxOK bit.

ITPUB
ITPUB
ITPUB
Why Does the RTL8139 Driver Miss the First TCP SYN? A Deep Dive into ISR Handling

During testing of TCP connections between a Linux machine and a board running the Papaya kernel, the kernel responded only to the second SYN packet while ignoring the first, leading to a driver bug in the RTL8139 network card.

Observed Behavior

The kernel received the first TCP SYN but gave no response.

When netcat retransmitted the SYN (automatic retry), the kernel responded, acknowledging the first SYN and ignoring the second, as expected.

By quickly aborting netcat before the retransmission, the developer saw that the driver read two packets in a single receive interrupt: the first being the TCP SYN.

Root Cause Analysis

The driver printed interrupt information indicating that a Tx (transmit) interrupt completed, but the expected Rx (receive) interrupt never occurred. The hypothesis is that the Rx interrupt arrived while the Tx interrupt routine was executing, and the Tx routine cleared the entire ISR register, including the ROK (receive‑ok) bit.

Consequently, the pending Rx interrupt was lost when the Tx routine finished.

Faulty Code

RTL_writew(netdev, ISR, 0xffff);

This line clears all bits in the ISR register, wiping out the RxOK flag.

Fix Implemented

RTL_writew(netdev, ISR, TxOK);

Only the TxOK bit is cleared, preserving any pending Rx interrupt flags.

Additional Context

The bug appears only when the Linux machine’s IP is set to 192.168.0.22 before the Papaya board boots. The Papaya kernel sends an ARP request to that address at startup; changing the IP prevents the ARP reply, causing the Linux side to issue its own ARP request before sending the TCP SYN. The rapid ARP reply triggers a Tx interrupt on the Papaya side, and the subsequent SYN arrives during that Tx interrupt routine, leading to the lost Rx interrupt.

Best Practice in Linux ISR Handling

Linux typically reads the ISR, clears all bits, then processes each pending flag individually:

int isr = RTL_readw(netdev, ISR);
RTL_writew(netdev, ISR, 0xfffff);
if (isr & RxOK)   /* handle receive */
if (isr & RxErr)  /* handle receive error */
if (isr & TxOK)   /* handle transmit */
...

Note that the checks are separate if statements, not an if‑else chain, allowing the kernel to handle multiple interrupt sources that may occur within a single ISR execution.

Reference

For the full source, see the modified rtl8139.c in Linux 2.6.38, available at the attached BBS link.

http://bbs.chinaunix.net/attachment.php?aid=NjkyMTI4fDliNzQ4YTYxfDE0Njg5MTgzNTZ8MzAyMDQ3OTF8NDI1MTEwMQ%3D%3D&fid=224

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Linux kernelISRinterrupt handlingdriver debuggingnetwork driver bugRTL8139TCP SYN loss
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.