`
sunzixun
  • 浏览: 75979 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

<linux kernel> RT8139c+ driver

 
阅读更多

 

 

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;

 

 

  • 大小: 8.7 KB
  • 大小: 289.6 KB
  • 大小: 21.9 KB
  • 大小: 39.9 KB
  • 大小: 25.5 KB
分享到:
评论

相关推荐

    RT3070 Linux驱动(包括 STA和 SoftAP驱动)

    1. 获取源代码:首先,从Ralink或开源社区获取到RT3070的Linux驱动源代码,例如通过下载名为"RT3070_Linux_driver"的压缩包。 2. 预处理:解压下载的压缩包,进入源代码目录。可能需要根据当前Linux内核版本对源...

    rt73-2.6.29-linux-driver

    描述中的“rt73 linux driver支持对应linux2.6.29kernel”进一步强调了这个驱动是专门为Linux内核2.6.29定制的。Linux内核是操作系统的核心部分,负责管理硬件资源、进程调度以及系统安全等关键任务。每个版本的内核...

    RT3070Wifi驱动

    6. **加载模块**:最后,用`sudo modprobe &lt;driver_name&gt;`命令加载驱动模块到内核,或者在`/etc/modules`文件中添加驱动名,使其在启动时自动加载。 7. **测试连接**:如果一切顺利,现在你应该可以在网络设置中...

    rt73无线网卡驱动源码 RT73_Android_Linux_STA_Drv1.1.0.2.tar.bz2

    RT73(RT2571W) Wireless Lan Linux Driver ======================================================================= Driver lName: =========== rt73 =========================================================...

    Jetson-Xavier-NX开发板重编译RT内核

    首先,解压Driver Package(BSP)Sources的下载文件public_sources.tbz2,进入解压后的Linux_for_Tegra目录,并解压内核源码kernel_src.tbz2。 然后,解压Driver Package(BSP)的下载文件Jetson_Linux_R35.4.1_...

    嵌入式Linux和嵌入式Linux开发环境.pdf

    - **实时性支持:** 通过RT-Linux等变种支持实时性能。 - **稳定性和安全性高:** 在长期发展中已经过多次验证。 **1.3 商业前景** 随着嵌入式技术的发展,嵌入式Linux展现出巨大的市场潜力和商业价值,吸引了许多...

    wireless Linux驱动

    6. 加载驱动:使用`sudo insmod &lt;driver_name&gt;.ko`或者通过`modprobe`命令加载驱动。 7. 检测网络设备:使用`iwconfig`或`ip link`查看无线网卡是否被识别。 8. 连接网络:设置网络参数,然后使用`iwconfig`或`wpa...

    kernel/userspace shared memory driver-开源

    然而,在某些高效率、低延迟的需求场景下,如实时Linux(RT-Linux)的任务或用户空间通信,传统的通信方式可能会因为额外的上下文切换和数据复制而产生性能瓶颈。为了解决这个问题,"mbuff.o"模块和"/dev/mbuff"设备...

    rtl8188FU_linux_v5.2.11.1_22924.20170703.tar.gz

    W:\tinav2.5\package\kernel\linux\modules\wireless.mk # # Copyright (C) 2006-2008 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more ...

    tomato-K26USB-1.28.0542-MIPSR2-8M.trx

    Linux kernel 2.6.22.19 and Broadcom Wireless Driver 5.10.56.46 updates, support for additional router models and Wireless-N mode. Copyright (C) 2008-2010 Fedor Kozhevnikov and Ray Van Tassle

    RTL8187网卡驱动

    3. 配置无线网络连接,可以使用`iwlist wlan0 scan`查找可用的无线网络,然后用`iwconfig wlan0 essid &lt;SSID&gt; key &lt;密码&gt;`连接。 4. 最后,使用`ifconfig wlan0 up`激活连接。 五、常见问题及解决方法 1. 如果驱动...

    Embedded Linux Primer 掌握嵌入式Linux

    - **Kernel**:Linux内核是操作系统的核心部分,负责管理系统的硬件资源和提供基本服务。 - **File Systems**:文件系统用于组织和存储数据。 - **Application Programs**:应用程序是运行在系统上的具体功能软件...

    SimIt-ARM-3.0 ARM指令模拟器

    usage : ema [-h] [-d] [-v] [-m num] [-s config] [&lt;file name&gt; &lt;args...&gt;] -h : print this message and quit -d : debuging mode -v : verbose mode -m num : maximum number of instructions to simulate, ...

    EtharCAT Master Documentation

    chips, as well as a generic driver for all chips supported by the Linux kernel. – The native drivers operate the hardware without interrupts. – Native drivers for additional Ethernet hardware can ...

    rtl8821cs_v5.12.0-8-g39bbb8dd2.20201015_COEX20200730-5151

    ko(Kernel Object)扩展名表示它是为Linux内核编译的模块。 2. **README** 或 **INSTALL** 文件:这些文档通常包含有关如何安装和配置驱动程序的步骤,以及可能遇到的问题和解决方法。 3. **源代码文件**:可能...

    zlgcantest.zip

    在Linux中,可以使用kernel.org提供的内核源码和kernel module开发工具链进行开发。 - **Windows调用接口**:通常,ZLG会提供API函数供用户应用程序调用,这些函数可能包括打开/关闭CAN接口、设置波特率、发送/接收...

    openwrt-mt7601u:用于OpenWRT固件的kuba-moo mt7601u驱动程序重写

    标题 "openwrt-mt7601u" 指的是一个专为OpenWRT固件设计的驱动程序重写项目,针对MT7601U...此外,了解Linux内核驱动开发的基本知识,如Kernel Driver模型、PCI设备驱动原理等,也将有助于理解并解决可能遇到的问题。

    ARM9_uCOS_II

    - **实时操作系统**:适用于对时间有严格要求的应用场景,如VxWorks、RTLinux等。 ### 操作系统基本概念 - **任务(Task)**:RTOS中的独立计算单元。 - **资源(Resource)**:RTOS中可被多个任务共享的数据或设备...

Global site tag (gtag.js) - Google Analytics