分类: LINUX
2005-09-23 17:39:41
ARCA GT2000 网卡内核驱动BUG引起的路由网络故障解决
我部设计了一款基于GT2000的防火墙,由其自带的网卡连接交换机芯片扩展8个RJ45口,其中,ARCAnet设备在系统中是eth0。问题如下:
问题:在连接一段时间后,ARCAnet-switch-8RJ45一线就不通了,但同一设备的其它网卡线路均运行正常。
# ARCA GT2000 网卡内核驱动BUG引起的路由网络故障解决
# 系统硬件平台
# ARCA gt2000/ 16M flash/ 128M DIMM SDRAM
#
# 20050823 由 LG 完成
# 其中关于代码和解决部分的技术支持由我的朋友“罗开辉”强力贡献,特此感谢,纪念!
# 我部设计了一款基于GT2000的防火墙,由其自带的网卡连接交换机芯片扩展8个RJ45口,其中,ARCAnet设备在系统中是eth0。问题如下:
# 问题:在连接一段时间后,ARCAnet-switch-8RJ45一线就不通了,但同一设备的其它网卡线路均运行正常。
故障检查:
1、交换部分,在断路后,连接到交换机的机器间通信正常,交换芯片温度低。
2、ARCAnet,断路后通过其他线路登陆防火墙检查,网络设备和系统均运行正常,没有数据错误和其他异常。
3、使用telnet登陆,ifconfig可以正确列出eth0设备的信息,可以正常ping通eth0,但却不能ping通与其连接的子网机器。
4、使用ifconfig eth0 down后,再将其 UP,此线路就又通了,再次出现此情况时重复此办法都可以恢复线路
5、网络中没有重复的MAC地址
6、在故障出现时系统打印内核信息“NETDEV WATCHDOG: eth0 transmit time out”
7、更换其他设计的硬件设备,故障依旧,排除芯片损坏。
故障分析:
基于以上信息,可以确定应用系统没有问题,怀疑是网卡电路设计有问题或者是网络设备驱动程序有BUG,
但是一个芯片的设计一般不会出现这种问题,周边电路也是模板电路,设计错误不大可能。
比较明确的信息是故障6的内核信息,确定由内核开始检查。
故障解决:
检查内核相关代码,发现:
上层协议发包超时时会调用设备驱动代码中注册的timeout_process函数,该函数定义如下
static void timeout_process(struct net_device *dev)
{
struct _t_mac_info * mac_info_p = (struct _t_mac_info *)dev->priv;
writel(1, mac_info_p->reg_base+DMA_TPD); // 停止硬件IO
mac_info_p->stats.tx_errors ++;
netif_wake_queue(dev); // 通知系统继续传输,???
DBPRINTK("[EXIT ----%s ] ",__FUNCTION__);
return;
}
很明显该函数中对于此的处理仅仅是记录下了出错计数,并唤醒了传输队列,但若此时是由于真正的硬件故障则如此处理则并不能解决问题,
而我们此时也只有将其恢复初始状态,这一办法可行.因此我们添加一个函数来复位设备
static void arca_eth_clean(struct net_device *dev);
第一步:
在drivers/net/arca-ethc.h中添加函数声明如下
static void arca_eth_clean(struct net_device *dev);
第二步:
在drivers/net/arca-ethc.c中添加函数定义
static void arca_eth_clean(struct net_device *dev)
{
int i;
struct _t_mac_info * mac_info_p = (struct _t_mac_info *)dev->priv;
netif_stop_queue(dev);
stop_eth(mac_info_p->reg_base);
synchronize_irq ();
DBPRINTK("[%s ---- %d] clean device",__FUNCTION__,__LINE__);
if (mac_info_p -> init_process != NULL)
(* mac_info_p->init_process)(dev);
dev->trans_start = jiffies;
mac_info_p->mac_state = MAC_ACTIVE;
driver_info.full_count = 0;
netif_start_queue(dev);
DBPRINTK("OK Now ");
}
代码功能:设备复位
详细解释:
1.终止协议栈队列向该设备发送数据包
2.向设备寄存器写入控制字,禁止其读写
3.等待其它设备中断完成
4.从新写各个寄存器,对设备初始化
5.向设备寄存器写入控制字,开启读写
6.通知协议栈可以向该设备发送数据包
第三步:在该文件的timeout_process(1032行)函数中的
writel(1, mac_info_p->reg_base+DMA_TPD);后面添加
arca_eth_clean(dev);
修改后代码如下
static void timeout_process(struct net_device *dev)
{
struct _t_mac_info * mac_info_p = (struct _t_mac_info *)dev->priv;
writel(1, mac_info_p->reg_base+DMA_TPD);
arca_eth_clean(dev);
mac_info_p->stats.tx_errors ++;
netif_wake_queue(dev);
DBPRINTK("[EXIT ----%s ] ",__FUNCTION__);
return;
}
重编译内核后,测试系统,问题解决。是ARCA的网卡本身不稳定么?