DM9000网卡驱动接受数据从中断方式改成NAPI方式小记
平台是最最经典的s3c2440了,说了要做这件事情很久了,就是改几行代码,一直没有做。前几天逼了自己一下,终于给做了,拖延症患者伤不起。
以下是需要读者对napi机制有所熟悉:
step1:在board_info结构体里面增加struct napi_struct napi;(这个还用说……)
step2:在dm9000_probe函数中增加netif_napi_add(ndev, &db->napi, dm9000_napi_poll, 64);
dm9000_napi_poll函数实现如下:
static int dm9000_napi_poll(struct napi_struct *napi, int budget)
{
board_info_t *db = container_of(napi, board_info_t, napi);
unsigned long flags;
u8 reg_save; spin_lock_irqsave(&db->lock, flags); reg_save = readb(db->io_addr); dm9000_rx(db->ndev, budget); napi_complete(napi); iow(db, DM9000_IMR, db->imr_all); writeb(reg_save, db->io_addr); spin_unlock_irqrestore(&db->lock, flags); return 0;
}
step3:在dm9000_open函数中增加napi_enable(&db->napi);//使能 NAPI
在dm9000_stop函数中增加napi_disable(&db->napi);//禁止 NAPI
step4:修改dm9000_interrupt中断函数,如下
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
board_info_t *db = netdev_priv(dev);
int int_status;
unsigned long flags;
u8 reg_save; dm9000_dbg(db, 3, "entering %s\n", __func__); /* A real interrupt coming */ /* holders of db->lock must always block IRQs */
spin_lock_irqsave(&db->lock, flags); /* Save previous register address */
reg_save = readb(db->io_addr); /* Disable all interrupts */
iow(db, DM9000_IMR, IMR_PAR); /* Got DM9000 interrupt status */
int_status = ior(db, DM9000_ISR); /* Got ISR */
iow(db, DM9000_ISR, int_status); /* Clear ISR status */ if (netif_msg_intr(db))
dev_dbg(db->dev, "interrupt status %02x\n", int_status); /* Received the coming packet */
if (int_status & ISR_PRS)//接受中断的话执行napi_schedule
{
napi_schedule(&db->napi);
} /* Trnasmit Interrupt check */
if (int_status & ISR_PTS)
dm9000_tx_done(dev, db); if (db->type != TYPE_DM9000E) {
if (int_status & ISR_LNKCHNG) {
/* fire a link-change request */
schedule_delayed_work(&db->phy_poll, 1);
}
} /* Re-enable interrupt mask */
if ((int_status & ISR_PRS) == 0)//如果不是接收函数,可以重新使能中断
iow(db, DM9000_IMR, db->imr_all); /* Restore previous register address */
writeb(reg_save, db->io_addr); spin_unlock_irqrestore(&db->lock, flags); return IRQ_HANDLED;
}
step5:修改接受函数,如下:
static void
dm9000_rx(struct net_device *dev, int budget)
{
board_info_t *db = netdev_priv(dev);
struct dm9000_rxhdr rxhdr;
struct sk_buff *skb;
u8 rxbyte, *rdptr;
bool GoodPacket;
int RxLen, rxTime = 0; /* Check packet ready or not */
do {
ior(db, DM9000_MRCMDX); /* Dummy read */ /* Get most updated data */
rxbyte = readb(db->io_data); /* Status check: this byte must be 0 or 1 */
if (rxbyte & DM9000_PKT_ERR) {
dev_warn(db->dev, "status check fail: %d\n", rxbyte);
iow(db, DM9000_RCR, 0x00); /* Stop Device */
iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */
break;
} if (!(rxbyte & DM9000_PKT_RDY))
break; /* A packet ready now & Get status/length */
GoodPacket = true;
writeb(DM9000_MRCMD, db->io_addr); (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr)); RxLen = le16_to_cpu(rxhdr.RxLen); if (netif_msg_rx_status(db))
dev_dbg(db->dev, "RX: status %02x, length %04x\n",
rxhdr.RxStatus, RxLen); /* Packet Status check */
if (RxLen < 0x40) {
GoodPacket = false;
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
} if (RxLen > DM9000_PKT_MAX) {
dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
} /* rxhdr.RxStatus is identical to RSR register. */
if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
RSR_PLE | RSR_RWTO |
RSR_LCS | RSR_RF)) {
GoodPacket = false;
if (rxhdr.RxStatus & RSR_FOE) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "fifo error\n");
dev->stats.rx_fifo_errors++;
}
if (rxhdr.RxStatus & RSR_CE) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "crc error\n");
dev->stats.rx_crc_errors++;
}
if (rxhdr.RxStatus & RSR_RF) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "length error\n");
dev->stats.rx_length_errors++;
}
} /* Move data from DM9000 */
if (GoodPacket &&
((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
skb_reserve(skb, 2);
rdptr = (u8 *) skb_put(skb, RxLen - 4); /* Read received packet from RX SRAM */ (db->inblk)(db->io_data, rdptr, RxLen);
dev->stats.rx_bytes += RxLen; /* Pass to upper layer */
skb->protocol = eth_type_trans(skb, dev);
if (db->rx_csum) {
if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb_checksum_none_assert(skb);
}
netif_rx(skb);
dev->stats.rx_packets++;
} else {
/* need to dump the packet's data */ (db->dumpblk)(db->io_data, RxLen);
}
rxTime++;
} while ((rxbyte & DM9000_PKT_RDY)&&(rxTime < budget));
// printk("rxTime:%d\n", rxTime);
}
改完了就可以开始测试了。
不过保险起见,最好在timeout、suspend、resume三个函数中增加响应的enable和disable函数。
性能上面的提升?呵呵~~~~~
移植中犯的一个错误,在中断函数里判断到是接收中断就直接调用完napi_schedule退出了,忽略了进中断的时候可能发送中断也被置位了的情况,结果老是timeout出错,这个是一个要注意的地方。进中断之后,可能是发送和接收中断同时置位了。
接下来就是要把dma机制移植上去,估计要花点时间了这个。
DM9000网卡驱动接受数据从中断方式改成NAPI方式小记的更多相关文章
- 【驱动】DM9000网卡驱动分析
Preface 内核源码版本:linux-2.6.18 网卡驱动·linux内核网络分层结构:http://infohacker.blog.51cto.com/6751239/122114 ...
- Linux网卡驱动移植--Dm9000网卡驱动分析
1. Linux网络体系结构由以下5部分组成 ① 系统调用接口: 位于Linux网络子系统的顶部,为应用程序提供访问内核网络子系统的方法,主要指socket系统调用. ② 协议无关接口: 实现一组基于 ...
- DM9000网卡驱动分析(转)
s3c6410自带的DM9000网卡驱动也是基于platform设备模型. 其定义的设备资源在arch/arm/mach-s3c64xx/mach-smdk6410中.有网卡的resource res ...
- iOS9 http不能访问网络——在Xcode中将https改成http方式
=====================2016-01-29更新=========================== 最近做demo时,发现将https改成http方式略有小变 1. 没有改成ht ...
- [国嵌攻略][136][DM9000网卡驱动深度分析]
网卡初始化 1.分配描述结构,alloc_etherdev 2.获取平台资源,platform_get_resource 2.1.在s3c_dm9k_resource中有相关的资源 2.2.add地址 ...
- DM9000网卡驱动深度分析
一.dm9000_porbe函数分析 不同于u-boot代码,tq2440中的DM9000更加复杂,需要分析的点也很多: /* * Search DM9000 board, allocate spac ...
- mini2440移植uboot-2008.10 (二) DM9000网卡驱动移植
还是利用 mini2440移植uboot-2008.10 (一) 修改好的代码 通过观察可以发现,mini2400使用的网卡芯片是DM9000,在uboot-2008.10源码中已经支持该芯片的驱动 ...
- [国嵌攻略][137][DM9000网卡驱动编程]
DM9000数据发送 DM9000数据发送函数是在/drivers/net/dm9000.c中的dm9000_start_xmit函数 static int dm9000_start_xmit(str ...
- Vmware改成bridge方式联网
1.在使用桥接之前,先在真机的'更改适配器设置中'禁用vmnet1和vmnet8 2.在VMware中定义一个桥接器 3.设置这个Linux虚拟机使用前一个步骤定义的桥接器--进入桥接器选择界面 4. ...
随机推荐
- Sum of Two integers
两个整数相加不能用加减 用位运算 假设两整数a=2和b=6,它们的二进制表示分别为010和110 sum=a^b表示两个二进制数相加不考虑进位: 010 ^ 110 = 100 carry=(a& ...
- VBS基本知识
由于一些需要,开始学习VBS了.此篇文章一直将处于编辑添加状态. 1.VBS简介 VBS 即VBScript(Microsoft Visual Basic Script Editon),是微软开发的一 ...
- Linux: vi 编辑器中文乱码
[问题] vi编辑器中文乱码 [解决方案] vi /etc/sysconfig/i18n改成如下即可:LANG="en_US.UTF-8"LANGUAGE="zh_CN. ...
- JS 計算文本域還能輸入多少個字符
//輸入計數 //count:能輸入的數據總量 function Calculation(v, count) { var span = $(v).next(); va ...
- CSS+HTML网页设计与布局(学习笔记1)
1.在宽度未知时,使div块居中,可以添加以下属性: display:table;margin:0 auto;
- mgo-后续测试(指定字段,获取id)
测试完mgo中的DBRef后,想接着测试指定字段的显示,才发现原来采用框架编码,很多问题被隐藏了起来: 1.显示指定字段: 之前在使用mgo时一直是查询全部字段,在mongo终端环境写为如下格式: & ...
- UVa 10055 - Hashmat the Brave Warrior
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=94&page=s ...
- 深入理解js——函数和对象的关系
函数也是对象,但是函数却不像数组--数组是对象的一种,它是对象的一个子集.函数和数组之间不是单纯的包含与被包含的关系,它们之间有点像鸡生蛋蛋生鸡的逻辑. 来例子:function Fn(){ this ...
- background-orgin属性
重点内容是:背景的显示范围是在元素的内边距之内的,如果要想改变显示范围,可以使用background-orgin和background-clip进行调整. (1)background-orgin有三个 ...
- No module named yum错误的解决办法
今天用yum安装软件的时候出现如下错误: There was a problem importing one of the Python modules required to run yum. Th ...