data reception in order to understand the process of NIC data reception. It is necessary to discuss the specific process of DMA first. The DMA transfer data can be divided into the following steps: First, the CPU sends commands to the DMA, such as DMA mode, main memory address, number of words transferred, etc., after which the CPU executes the original program. Then the DMA controls the I/O device and the main memory. Exchange data between. After receiving the data, send a DMA request to the CPU, obtain the bus control right, perform data transfer, modify the main memory address on the card, modify the word counter and check whether the value is zero, if it is not zero, continue to transmit, if it is zero , then send an interrupt request to the CPU. In other words, when the NIC receives the packet, it is placed in the current skb->data. When you come back to a package. The DMA will modify the main memory address on the card, go to skb->next, and put the data into it. That is why a skb->data stores a packet. Ok, now you can see the specific code implementation. When the network data arrives, the network card puts it into the DMA memory, and then the DMA reports the interrupt to the CPU. The CPU finds the interrupt processing routine according to the interrupt vector, which is the e100_intr() registered by us. Static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs){struct net_device *netdev = dev_id;struct nic *nic = netdev_priv(netdev);u8 stat_ack = readb(&nic->csr->scb .stat_ack);DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\ ", stat_ack);if(stat_ack == stat_ack_not_ours |
|
/* Not our interrupt */stat_ack == stat_ack_not_present) /* Hardware is ejected */return IRQ_NONE;/* Ack interrupt(s) *///Send interrupt ACK. The CPU sends an ACK to the device. Indicates that this interrupt has been processed for writeb(stat_ack, &nic->csr->scb.stat_ack);/* We hit Receive No Resource (RNR); restart RU after cleaning */if(stat_ack & stat_ack_rnr)nic- >ru_running = 0; //disable interrupt e100_disable_irq (nic); //CPU began to schedule this device. Instead, running netdev->pollnetif_rx_schedule(netdev);return IRQ_HANDLED;}netif_rx_schedule(netdev), the cpu starts scheduling the device and polls the device for data to process. After the call, call the netdev->poll function, ie: e100_poll() static int e100_poll(struct net_device *netdev, int *budget){struct nic *nic = netdev_priv(netdev);unsigned int work_to_do = min(netdev->quota , *budget);unsigned int work_done = 0;int tx_cleaned;//Start NIC, DMA data processing e100_rx_clean(nic, &work_done, work_to_do);tx_cleaned = e100_tx_clean(nic);/* If no Rx and Tx Cleanup work was done, exit polling mode. */if((!tx_cleaned && (work_done == 0)) |
|
!netif_running(netdev)) {netif_rx_complete(netdev);e100_enable_irq(nic);return 0;}*budget -= work_done;netdev->quota -= work_done;return 1;}Track into e100_rx_clean():static inline void e100_rx_clean (struct nic *nic, unsigned int *work_done, unsigned int work_to_do){struct rx *rx;/* Indicated newly arrived packets *///traverse the data in the ring DMA, call e100_rx_indicate() for processing for(rx = nic- >rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {if(e100_rx_indicate(nic, rx, work_done, work_to_do))break; /* No more to clean */}/* Alloc new skbs to refill list */for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {if(un100ly_ex_alloc_skb(nic, rx )))break; /* Better luck next time (see watchdog) */}e100_start_receiver(nic);} Here, it will traverse the data in the ring DMA, that is, the data starting from nic->rx_to_clean until the data is all Processed into the handler: e100_rx_indicate() static inline int e100_rx_indicate(struct nic *nic, struct Rx *rx,unsigned int *work_done, unsigned int work_to_do){struct sk_buff *skb = rx->skb;//Get rfd from here. It includes some received information, but not valid data from the link struct rfd *rfd = (struct rfd *)skb->data;u16 rfd_status, actual_size;if(unlikely(work_done && *work_done >= work_to_do))return -EAGAIN;//synchronous DMA cache pci_dma_sync_single_for_cpu(nic-> ;pdev, rx->dma_addr,sizeof(struct rfd), PCI_DMA_FROMDEVICE);//Get the receive status rfd_status = le16_to_cpu(rfd->status);DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\ " , rfd_status);/* If data isn't ready, nothing to indicate *///No reception is complete, return
Matthew Garrett, Core Developer from Red Hat, publishes a detailed article on Fedora 18. It will int
The SELinux function is an implementation of mandatory access control, which can
nmap is a network port scanner. Its main function is to check a group of target hosts to see which
How to effectively perform Linux patch management Red Hat LinuxOSRHEL patch can be installed throug
Linux Netcat command usage tutorial
Linux system DNS package uninstallation and installation method
Linux device driver development environment build
Terminal garbled under Linux operating system
Centos6 opens the disk quota function of the EXT4 file system
How to start and shut down Linux system
CentOS installation GD library support
Scp copying between Linux hosts without entering a password
Do not blame the actual Linux operating system dual screen display
Win8.1 wireless network limited solution
Sorry! The game has some problems. First restart the client. Solution
[Video] Win10 Mobile10536.1004 preview version of the experience
Recording music with Windows built-in recorder
Win7 right click on the computer icon can not open the property how to break?
Win10 default browser how to set up? Win10 set Edge as the default browser method
The latest Win10 system upgrade official ISO download tool can be directly upgraded Win10 TH2