免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12345下一页
最近访问板块 发新帖
查看: 11177 | 回复: 40
打印 上一主题 下一主题

请教e100 网卡驱动的几个问题, [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-02-15 16:32 |只看该作者 |倒序浏览
我最近一段时间在学习e100.c的驱动程序,有几个地方看的不是很明白

1.网卡在接收到数据包时,是先中断通知数据到达然后dma传送数据包,还是先dma传送数据包然后中断通知数据到达?

2.进入poll查询方式后,屏蔽了中断,是否还可以接收数据包?

3.退出poll查询方式后,如果收到一个数据包,按照代码中e100_intr的写法,是不是马上又会屏蔽中断?

static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *netdev = dev_id;
struct nic *nic = netdev_priv(netdev);
u8 stat_ack = readb(&nic->csr->scb.stat_ack);

DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack);

if(stat_ack == stat_ack_not_ours || /* Not our interrupt */
stat_ack == stat_ack_not_present) /* Hardware is ejected */
return IRQ_NONE;

/* Ack interrupt(s) */
writeb(stat_ack, &nic->csr->scb.stat_ack);

/* We hit Receive No Resource (RNR); restart RU after cleaning */
if(stat_ack & stat_ack_rnr)
nic->ru_running = RU_SUSPENDED;


if(likely(netif_rx_schedule_prep(netdev))) {
e100_disable_irq(nic);
__netif_rx_schedule(netdev);
}

return IRQ_HANDLED;
}
4. 在 e100_rx_indicate函数中,
/* this allows for a fast restart without re-enabling interrupts */
        if(le16_to_cpu(rfd->command) & cb_el)
                nic->ru_running = RU_SUSPENDED;
这段代码的作用是干嘛的啊??

论坛徽章:
0
2 [报告]
发表于 2008-02-15 17:07 |只看该作者
不懂ethernet,只是尝试回答一下, 请大家FIXME:

> 1.网卡在接收到数据包时,是先中断通知数据到达然后dma传送数据包,还是先dma传送数据包然后中断通知数据到达?
应该是先中断,然后driver启动DMA,DMA传输完成后又会发出一个中断。

> 2.进入poll查询方式后,屏蔽了中断,是否还可以接收数据包?
可以,因为虽然收不到中断了,但是CPU主动去询问网卡是否有数据包

> 3.退出poll查询方式后,如果收到一个数据包,按照代码中e100_intr的写法,是不是马上又会屏蔽中断?
看这个逻辑,似乎是: 既然CONFIG_NAPI了,那么满足条件的话就必须走NAPI。

> 4.
不懂,应该是和e100芯片的控制寄存器有关的吧。

论坛徽章:
0
3 [报告]
发表于 2008-02-16 14:40 |只看该作者
原帖由 albcamus 于 2008-2-15 17:07 发表
不懂ethernet,只是尝试回答一下, 请大家FIXME:

> 1.网卡在接收到数据包时,是先中断通知数据到达然后dma传送数据包,还是先dma传送数据包然后中断通知数据到达?
应该是先中断,然后driver启动DMA,DMA ...

正好给QEMU写过一个E100的设备模拟程序,有点心得。先纠正albcamus
>> 1.网卡在接收到数据包时,是先中断通知数据到达然后dma传送数据包,还是先dma传送数据包然后中断通知数据到达?
>应该是先中断,然后driver启动DMA,DMA传输完成后又会发出一个中断。
是先DMA再中断。网卡将收到的数据DMA到一个链表(称为RFD, receive frame descriptor,每个RFD由header和data部分构成,组成一个链表),网卡判断RFD的header中的i标志是否置1,是的话产生中断通知driver。
此外,DMA是一个硬件自动的行为,通常是在初始化阶段driver把一个ring buffer的地址写到硬件的某个寄存器中,硬件在收到数据后直接DMA到该内存,再产生中断通知driver。还没见到过先中断,再由driver发起的DMA的硬件,如有请FIX ME。

此外是LZ的问题。
> 2.进入poll查询方式后,屏蔽了中断,是否还可以接收数据包?
方式和albcamus说的一样。但我似乎没看到E100有poll方式,或许是因为我基于的是老型号的i82557网卡的缘故。LZ可以查阅它的spec

> 3.退出poll查询方式后,如果收到一个数据包,按照代码中e100_intr的写法,是不是马上又会屏蔽中断?
因为收到的包是放到一个RFD链表中的,所以driver要负责处理这个链表并将已递交出去的RFD重利用,每次收到包都会做这种检查,在这个期间要关闭中断。
此外,E100的中断处理函数也就是e100_intr是有bug的。LZ可以看看它这里先读了nic->csr->scb.stat_ack,然后把它写回去作为中断应答(这个是E100规定方式,参见spec)。但是如果在读取stat_ack后,写回应答前产生了新的中断,硬件的stat_ack寄存器就会发生变化(stat_ack每一位代表一种中断),这个时候再把老的值写入这个寄存器,新产生的中断就得不到应答。硬件在产生中断前会检查以前的中断是否得到应答,如果没有,则不会再产生中断。这个未应答的中断就会阻止新中断的产生,在driver看来,硬件不工作了。

这个bug在普通的机器上不会出现,是因为真实机器做一次IO比较快(做IO的速度比中断产生速度快)。但在QEMU这种做IO比较慢的模拟器上,问题就暴露出来了。惭愧,由于懒,一直未向社区报告这个bug。老的eepro100驱动就没这个问题,它采用了正确的循环应答方式。LZ可以参考。
> 4.
参见E100的spec,RFD中的el位表示这个是链表中最后一个元素。这种情况表明用于接收数据包的RFD链表被耗尽了,这个时候就该把硬件设置成suspend状态,不接收新的包了。这种情况通常不会产生,因为每次中断处理的时候都会判断是否需要回收RFD,达到循环利用的目的



虽然读硬件的spec是非常痛苦的事情,但如果LZ想真正把这个驱动看懂,那你必须阅读它,我作为附件上传

再同albcmus一起骂一次,TMD intel和MS的spec真是又臭又长 --- 175页,别人8139的才30多页

8255X_OpenSDM.rar

927.65 KB, 下载次数: 1732

论坛徽章:
0
4 [报告]
发表于 2008-02-18 09:36 |只看该作者
原帖由 zx_wing 于 2008-2-16 14:40 发表
正好给QEMU写过一个E100的设备模拟程序,有点心得。先纠正albcamus
>> 1.网卡在接收到数据包时,是先中断通知数据到达然后dma传送数据包,还是先dma传送数据包然后中断通知数据到达?
>应该是先中断,然后driver启动DMA,DMA传输完成后又会发出一个中断。
是先DMA再中断。网卡将收到的数据DMA到一个链表(称为RFD, receive frame descriptor,每个RFD由header和data部分构成,组成一个链表),网卡判断RFD的header中的i标志是否置1,是的话产生中断通知driver。
此外,DMA是一个硬件自动的行为,通常是在初始化阶段driver把一个ring buffer的地址写到硬件的某个寄存器中,硬件在收到数据后直接DMA到该内存,再产生中断通知driver。还没见到过先中断,再由driver发起的DMA的硬件,如有请FIX ME。


谢谢,我把这段话记到笔记中了

论坛徽章:
0
5 [报告]
发表于 2008-02-18 10:31 |只看该作者
是吗?

看看去 呵呵  谢谢 上面的 青蛙

论坛徽章:
0
6 [报告]
发表于 2008-02-18 11:30 |只看该作者
谢谢各位兄弟, spec我要慢慢阅读, 呵呵,太感谢了

论坛徽章:
0
7 [报告]
发表于 2008-02-18 12:25 |只看该作者
> 2.进入poll查询方式后,屏蔽了中断,是否还可以接收数据包?
可不可以理解为: 虽然屏蔽了中断, 但网卡还是可以把接受到的数据写入RFD的链表中,poll的时候其实是对RFD链表做处理的?

论坛徽章:
0
8 [报告]
发表于 2008-02-18 12:30 |只看该作者
>3, 我看了2.6.23代码中的E100.c中的代码:
u8 stat_ack = ioread8(&nic->csr->scb.stat_ack);
DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack);
if(stat_ack == stat_ack_not_ours ||              /* Not our interrupt */
        stat_ack == stat_ack_not_present)        /* Hardware is ejected */
        return IRQ_NONE;

/* Ack interrupt(s) */
iowrite8(stat_ack, &nic->csr->scb.stat_ack);
确实像zx_wing 兄弟说的一样, 这段时间内如果寄存器发生变化, 确实有问题.

zx_wing 老兄能否将你的处理方法教教兄弟,

[ 本帖最后由 libo500k 于 2008-2-18 12:34 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2008-02-18 13:26 |只看该作者
原帖由 libo500k 于 2008-2-18 12:25 发表
> 2.进入poll查询方式后,屏蔽了中断,是否还可以接收数据包?
可不可以理解为: 虽然屏蔽了中断, 但网卡还是可以把接受到的数据写入RFD的链表中,poll的时候其实是对RFD链表做处理的?

是可以这样做,只是我不记得E100里面怎么设置是采用poll模式

论坛徽章:
0
10 [报告]
发表于 2008-02-18 13:27 |只看该作者
原帖由 libo500k 于 2008-2-18 12:30 发表
>3, 我看了2.6.23代码中的E100.c中的代码:
u8 stat_ack = ioread8(&nic->csr->scb.stat_ack);
DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack);
if(stat_ack == stat_ack_not_ours ||               ...

处理方法很简单,加个do ... while, 当读出的stat_ack为0表示所有中断都应答了,再退出。
参考eepro100.c中的中断处理函数,那个是对的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP