NIC register
IntrStatus = 0x3E, /* Interrupt status */
int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|- dev->irq = pdev->irq;
Int Cp_open(struct net_device *dev)
|-Request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name , dev);
#define cpr16(reg) readw(cp->regs + (reg))
cp_norx_intr_mask = PciErr | LinkChg | TxOK | TxErr | TxEmpty,
Irqreturn_t cp_interrupt(int irq, void *dev_instance){
//...
if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
if (napi_schedule_prep(&cp->napi)) {
// 关闭 recv中断相关寄存器 进入NAPI模式
cpw16_f(IntrMask, cp_norx_intr_mask);
__napi_schedule(&cp->napi);
|-____napi_schedule(&__get_cpu_var(softnet_data), n);
|- __raise_softirq_irqoff(NET_RX_SOFTIRQ);
}
status = cpr16(IntrStatus);
//...
}
static inline int napi_schedule_prep(struct napi_struct *n)
|-test_and_set_bit(NAPI_STATE_SCHED, &n->state);
:/proc/sys/net/core$ cat netdev_budget 300
Static void net_rx_action(struct softirq_action *h){
struct softnet_data *sd = &__get_cpu_var(softnet_data);
while (!list_empty(&sd->poll_list)) {
//...
if (test_bit(NAPI_STATE_SCHED, &n->state)) {
work = n->poll(n, weight);
trace_napi_poll(n);
}
WARN_ON_ONCE(work > weight);
budget -= work; //你懂的
//..
}
}
Recall to :
process_backlog()
|-struct softnet_data *sd = container_of(napi, struct softnet_data, backlog);
|-__netif_receive_skb
// ok 忘记吧!
-----------------------------------------------------------------------------------------------------
Here we back to 8139 driver :
// 开始从DMA 搬运到 cp->rx_skb
void cp_rx_poll(struct napi_struct *napi, int budget){
//...
While(1){
const unsigned buflen = cp->rx_buf_sz;
skb = cp->rx_skb[rx_tail];
len = (status & 0x1fff) - 4; //CRC
// |- cp_change_mtu(); -> cp_set_rxbufsize();
new_skb = netdev_alloc_skb_ip_align(dev, buflen);
|-__netdev_alloc_skb+GFP_ATOMIC
|-skb_reserve+NET_IP_ALIGN
/*ummpa上次的dma 地址 last transfer is done */
dma_unmap_single(&cp->pdev->dev, mapping, buflen, PCI_DMA_FROMDEVICE);
skb_put(skb, len);
/*用new_skb->data做为下一次的mapping 并保存*/
mapping = dma_map_single(&cp->pdev->dev, new_skb->data, buflen,PCI_DMA_FROMDEVICE);
/*记录在 rx_skb数组tail*/
cp->rx_skb[rx_tail] = new_skb;
cp_rx_skb(cp, skb, desc);
|-__napi_gro_receive 使用GRO开始做拆包的组装
|-dev_gro_receive
|-ptype->gro_receive(&napi->gro_list, skb); 先是inet_gro_receive 接下来如果tcp 注册的是tcp4_gro_receive skb都存到了skb_shared_info frags上
cp->rx_ring[rx_tail].opts2 = 0;
cp->rx_ring[rx_tail].addr = cpu_to_le64(mapping);
//some statistics
if (rx < budget) {// done !}
}
//...
}
The streaming DMA mapping routines can be called from interrupt context.
不需要CPU 和device 之间 in parallel access
This of "streaming" as "asynchronous" or "outside the coherency domain".
对于 ring descriptors 需要Consistent DMA
static int cp_alloc_rings (struct cp_private *cp)
{
void *mem;
mem = dma_alloc_coherent(&cp->pdev->dev, CP_RING_BYTES,
&cp->ring_dma, GFP_KERNEL);
if (!mem)
return -ENOMEM;
// 记住操作此mem 如果不想发生奇怪的事情一定要wmb()一下!
cp->rx_ring = mem;
cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];//64
return cp_init_rings(cp);
这里就要说一下8139c+的 transmit receive mode了
rtl8139c+ 为收发单独提供了【64】个连续的内存描述符 有3种ring 描述符,
1 高优先级传输ring
2 正常优先级传输ring
3 正常接收ring
每一个ring描述符 由4个连续的双字组成 ,开始地址也需要256位对齐, 这里可以看到预先用consistent DMA分配了这块
下面是区段对这个的定义,很简单? NO
struct cp_desc {
__le32 opts1;
__le32 opts2;
__le64 addr;
};
事实上应该如此:
分配ring 数组
int cp_alloc_rings(struct cp_private *cp)
|- dma_alloc_coherent + GFP_KERNEL
|- __get_free_pages /
-----------------------------------------------------------
E2prom :
cp_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 *data)
addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
相关推荐
html<br>ISP-Connectivity-html<br>ISP-Hookup-HOWTO-html<br>Java-CGI-HOWTO-html<br>Kerneld<br>Kernel-HOWTO-html<br>Large-Disk-html<br>LinuxDoc+Emacs+Ispell-HOWTO-html<br>Linux+DOS+Win95<br>Linux+FreeBSD...
The+Linux+Kernel+Module+Programming+Guide+2.6
it can help you significantly reduce operation costs, enhance availability, and improve ROI.<br/><br/>Discover proven best practices for diagnosing problems in Linux environments<br/><br/>Leverage ...
The+Linux+Kernel+Module+Programming+Guide--2.6.4 注意版本不同可能导致编辑不成功,所以注意选择哈 很经典的linux内核模块编程指南
<br><br>1 Linux Programming 1<br>1.1 Linux Useful Programming ...Driver Module 9<br>1.4.1 User Space and Kernel Space 10<br>1.4.2 Linux Linking a module to the kernel 10<br>1.4.3 Using the /proc ...
三本经典内核书籍+linux kernel api+linux device model Linux Device Drivers,3rd Edition.chm The Linux Kernel Module Programming Guide 2.6.pdf linux-api-2.6.22.chm 深入理解linux内核.pdf linux 2.6 device ...
Major topics include:<br><br><br><br>GNU and Unix commands<br><br>Linux installation and package management<br><br>Devices, filesystems, and kernel configuration<br><br>Text editing, processing, and ...
2018\09\10 周一 17:27 <DIR> Kernel mode display-only miniport driver (KMDOD) sample 2018\09\10 周一 17:27 <DIR> Keyboard Input WDF Filter Driver (Kbfiltr) 2018\09\10 周一 17:27 <DIR> Keyboard Layout ...
<br/><br/>Key Features:<br/><br/>Focuses on GNU/ Linux, not only the Linux APIs, but the GNU tools and libraries that make Linux programming possible <br/>Covers a variety of useful APIs for process ...
The problem is related to core components functioning peculiarities after updating Windows 2003 to SP2.<br><br>The issue is fixed in the new Outpost driver.<br><br>Please replace the firewall driver ...
Linux 5.19 kernel + patch RT
<br>GCC-HOWTO (33KB) 如何安装GNUC编译器和程式库的方法 <br>Glibc2-HOWTO (13KB) 如何在Linux系统上安装与使用第二版 GNU C Library <br>Hardware-HOWTO (42KB) 详列了大部份被 Linux 所支援的硬件和驱动程序 <br...
linux kernel driver 框架介绍,进行linux driver 开发必备资料
这是一个简单的基于C语言的防火墙,#include <linux/kernel.h> #include <linux/ip.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #...
分享一个来自free electrons公司推出的Linux Kernel and Driver Development Training文档。
linux kernel development+linux device model+understanding the linux kernel all english version
Embedded Linux Kernel and Driver Development
#include <linux/kernel.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/init...
Microsoft Kernel-Mode Driver Framework Install-v1.9 for vista/win2K/winxp/win2k3