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. ...
随机推荐
- CSS中的相对定位和绝对定位
1.元素的position属性的值默认为static 就是没有定位,元素出现在正常的文档流中,,这个时候你给这个元素设置的left,right,bottom,top这些偏移属性都是没有效果的, 使用相 ...
- operator 的两种用法
C++,有时它的确是个耐玩的东东,就比如operator,它有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换).1.操作符 ...
- Python自动化 【第八篇】:Python基础-Socket编程进阶
本节内容: Socket语法及相关 SocketServer实现多并发 1. Socket语法及相关 sk = socket.socket(socket.AF_INET,socket.SOCK_STR ...
- Junit测试中的setup和teardown 和 @before 和 @After 方法
这几天做Junit测试接触到了setup和teardown两个方法,简单的可以这样理解它们,setup主要实现测试前的初始化工作,而teardown则主要实现测试完成后的垃圾回收等工作. 需要注意的是 ...
- Lambda 表达式的基本形式
基本形式: (input parameters) => expression 其中:运算符“=>”读作“goes to”. 例如: () => 5 * 3; (x) => x ...
- 解决PHP在IE中下载文件,中文文件名乱码问题
if( stripos($_SERVER['HTTP_USER_AGENT'], 'MSIE')!==false ) $filename = urlencode( $filename ); // 输入 ...
- 京东B2B的4种供销模式
B2B的4种供销模式,以京东商城为例: FBP 京东给商家一个独立操作的后台, 商家五地入库(北京,上海,广州,成都,武汉),从仓储 到配送 到客服都是京东来操作, 京东本身自营的产品所有能享 ...
- 调用百度地图API的应用混淆后出问题
1 混淆后出问题,程序异常退出 在proguard-project.txt中添加 -libraryjars libs/BaiduLBS_Android.jar -keep class com.baid ...
- 1-9 TCP/IP参考模型
ISO/OSI参考模型与TCP/IP模型对比 一.网络访问层 功能:包括IP地址与物理硬件地址的映射以及将IP地址封装成帧. 基于不同类型的网络接口,网路访问层定义了和物理介质的连接 网路访问层包含了 ...
- [刘阳Java]_Java程序员的成长路线_第3讲
按照Java从业人员的职位晋升来说,Java程序成长路线大致如下 Java程序员 JavaEE初级软件工程师 JavaEE中级软件工程师 JavaEE高级软件工程师 Java架构师 按照职业发展方向, ...