平台是最最经典的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方式小记的更多相关文章

  1. 【驱动】DM9000网卡驱动分析

    Preface    内核源码版本:linux-2.6.18    网卡驱动·linux内核网络分层结构:http://infohacker.blog.51cto.com/6751239/122114 ...

  2. Linux网卡驱动移植--Dm9000网卡驱动分析

    1. Linux网络体系结构由以下5部分组成 ① 系统调用接口: 位于Linux网络子系统的顶部,为应用程序提供访问内核网络子系统的方法,主要指socket系统调用. ② 协议无关接口: 实现一组基于 ...

  3. DM9000网卡驱动分析(转)

    s3c6410自带的DM9000网卡驱动也是基于platform设备模型. 其定义的设备资源在arch/arm/mach-s3c64xx/mach-smdk6410中.有网卡的resource res ...

  4. iOS9 http不能访问网络——在Xcode中将https改成http方式

    =====================2016-01-29更新=========================== 最近做demo时,发现将https改成http方式略有小变 1. 没有改成ht ...

  5. [国嵌攻略][136][DM9000网卡驱动深度分析]

    网卡初始化 1.分配描述结构,alloc_etherdev 2.获取平台资源,platform_get_resource 2.1.在s3c_dm9k_resource中有相关的资源 2.2.add地址 ...

  6. DM9000网卡驱动深度分析

    一.dm9000_porbe函数分析 不同于u-boot代码,tq2440中的DM9000更加复杂,需要分析的点也很多: /* * Search DM9000 board, allocate spac ...

  7. mini2440移植uboot-2008.10 (二) DM9000网卡驱动移植

    还是利用 mini2440移植uboot-2008.10 (一)  修改好的代码 通过观察可以发现,mini2400使用的网卡芯片是DM9000,在uboot-2008.10源码中已经支持该芯片的驱动 ...

  8. [国嵌攻略][137][DM9000网卡驱动编程]

    DM9000数据发送 DM9000数据发送函数是在/drivers/net/dm9000.c中的dm9000_start_xmit函数 static int dm9000_start_xmit(str ...

  9. Vmware改成bridge方式联网

    1.在使用桥接之前,先在真机的'更改适配器设置中'禁用vmnet1和vmnet8 2.在VMware中定义一个桥接器 3.设置这个Linux虚拟机使用前一个步骤定义的桥接器--进入桥接器选择界面 4. ...

随机推荐

  1. Sum of Two integers

    两个整数相加不能用加减 用位运算 假设两整数a=2和b=6,它们的二进制表示分别为010和110 sum=a^b表示两个二进制数相加不考虑进位: 010 ^  110 =  100 carry=(a& ...

  2. VBS基本知识

    由于一些需要,开始学习VBS了.此篇文章一直将处于编辑添加状态. 1.VBS简介 VBS 即VBScript(Microsoft Visual Basic Script Editon),是微软开发的一 ...

  3. Linux: vi 编辑器中文乱码

    [问题] vi编辑器中文乱码 [解决方案] vi /etc/sysconfig/i18n改成如下即可:LANG="en_US.UTF-8"LANGUAGE="zh_CN. ...

  4. JS 計算文本域還能輸入多少個字符

    //輸入計數 //count:能輸入的數據總量    function Calculation(v, count) {        var span = $(v).next();        va ...

  5. CSS+HTML网页设计与布局(学习笔记1)

    1.在宽度未知时,使div块居中,可以添加以下属性: display:table;margin:0 auto;

  6. mgo-后续测试(指定字段,获取id)

    测试完mgo中的DBRef后,想接着测试指定字段的显示,才发现原来采用框架编码,很多问题被隐藏了起来: 1.显示指定字段: 之前在使用mgo时一直是查询全部字段,在mongo终端环境写为如下格式: & ...

  7. UVa 10055 - Hashmat the Brave Warrior

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=94&page=s ...

  8. 深入理解js——函数和对象的关系

    函数也是对象,但是函数却不像数组--数组是对象的一种,它是对象的一个子集.函数和数组之间不是单纯的包含与被包含的关系,它们之间有点像鸡生蛋蛋生鸡的逻辑. 来例子:function Fn(){ this ...

  9. background-orgin属性

    重点内容是:背景的显示范围是在元素的内边距之内的,如果要想改变显示范围,可以使用background-orgin和background-clip进行调整. (1)background-orgin有三个 ...

  10. No module named yum错误的解决办法

    今天用yum安装软件的时候出现如下错误: There was a problem importing one of the Python modules required to run yum. Th ...