Linux网卡驱动如何通知NIC发送数据?sky2驱动相关技术问询
Great question! It's totally normal to miss the hardware trigger logic in sky2_xmit_frame—this driver encapsulates that low-level interaction in helper functions, rather than putting it directly in the ndo_start_xmit handler. Let's break down exactly how it works:
1. The Core Trigger: Updating the TX Tail Register
The main way the sky2 driver tells the NIC about new packets is by updating the TX Tail Register after adding packets to the transmit ring buffer:
- After
sky2_xmit_framefinishes unpacking the skb and filling the transmit descriptors, it updates the software-side tail pointer for the transmit queue (struct sky2_tx_queue *q). - It then writes this new tail pointer to the NIC's hardware register using
sky2_write32(adapter, SK_REG_TX_TAIL(q->idx), q->tail). - Most Broadcom NICs (the ones the sky2 driver targets) continuously monitor this register. When they see the tail pointer move forward, they automatically start pulling new packets from the ring buffer for transmission.
2. Wake-Up Logic for Stopped TX Queues
If the transmit queue was previously stopped (e.g., because it was full and the NIC paused transmission), the driver will explicitly wake up the hardware:
- This happens in a helper function like
sky2_tx_queue_wake, which writes a command to the NIC'sSK_REG_CMDregister (usuallySK_CMD_TX_START) to restart the transmit engine. - This logic only runs when the queue transitions from a stopped state to a ready state, so you won't see it in every call to
sky2_xmit_frame.
3. Why You Didn't See It in sky2_xmit_frame
The sky2 driver abstracts hardware interactions to keep the main transmit handler clean. Here's a simplified snippet of what the underlying logic looks like in the actual driver code to illustrate:
static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); struct sky2_tx_queue *q = &sky2->txq[skb->queue_mapping]; // ... Unpack skb, fill transmit descriptors ... // Advance the software tail pointer q->tail = (q->tail + 1) & q->mask; // Notify NIC of the new tail position sky2_write32(sky2->adapter, SK_REG_TX_TAIL(q->idx), q->tail); // If the queue was stopped, wake up the NIC's transmit engine if (q->stopped) { sky2_tx_queue_wake(q); q->stopped = false; } return NETDEV_TX_OK; }
Quick Recap
The sky2 driver uses two key mechanisms to trigger transmission:
- Tail register updates: The primary method—NICs auto-detect changes to this register and process new packets.
- Explicit wake-up commands: Used only when the transmit queue was paused, to restart the hardware engine.
内容的提问来源于stack exchange,提问作者S.Wan

