前言
环境介绍:
1.编译环境
Ubuntu 18.04.5 LTS
2.SDK
T113-i_v1.0
3.单板
迅龙TLT113-EVM-A1.1-000 + 自制底板
# 一、现象
插上网线启动,内核打印信息正常
 
 不插网线启动,内核存在CPU崩溃打印[ cut here ]
 
二、问题根因
根据错误提示找到
 /home/zfeng/T113- v1.8/kernel/linux-5.4/drivers/net/phy/phy.c:839 phy stop
 phy_stop用于中止soc的gmac与phy的链接。
/**
 * phy_stop - Bring down the PHY link, and stop checking the status
 * @phydev: target phy_device struct
 */
void phy_stop(struct phy_device *phydev)
{
	if (!phy_is_started(phydev)) {
		WARN(1, "called from state %s\n",
		     phy_state_to_str(phydev->state));
		return;
	}
	mutex_lock(&phydev->lock);
	phydev->state = PHY_HALTED;
	mutex_unlock(&phydev->lock);
	phy_state_machine(&phydev->state_queue.work);
	phy_stop_machine(phydev);
	/* Cannot call flush_scheduled_work() here as desired because
	 * of rtnl_lock(), but PHY_HALTED shall guarantee irq handler
	 * will not reenable interrupts.
	 */
}
EXPORT_SYMBOL(phy_stop);
phy_stop该函数在
 /home/zfeng/T113-i_v1.0/kernel/linux-5.4/drivers/net/ethernet/allwinner/sunxi-gmac.c→geth_phy_release引用
static int geth_phy_release(struct net_device *ndev)
{
... ...
	/* Stop and disconnect the PHY */
	if (phydev)
		phy_stop(phydev);
... ...
}
而函数geth_phy_release 在static int geth_stop(struct net_device *ndev)、static int geth_open(struct net_device *ndev)都有被引用。
static int geth_stop(struct net_device *ndev)
{
... ...
	/* Release PHY resources */
	geth_phy_release(ndev);
... ...
}
static int geth_open(struct net_device *ndev)
{
... ...
if (!priv->is_suspend) {
	ret = geth_dma_desc_init(ndev);
	if (ret) {
		ret = -EINVAL;
		goto desc_err;//当没插入网线,会执行desc_err 中断网络配置
	}
}
... ...
//该内容被跳过了
if (ndev->phydev)
	phy_start(ndev->phydev);
... ...
desc_err:
geth_phy_release(ndev);
... ...
}
从geth_open函数可以看到,当没插入网线,会执行desc_err 中断网络配置,跳过 phy_start(ndev->phydev),直接执行geth_phy_release的phy_stop(phydev),导致cpu执行了空指针或是空函数出错。
 如果从启动正常把网线插入,geth_open将正常执行完,phy_start(ndev->phydev)也会正常执行,这样当将网络down,geth_stop可以正常执行phy_stop不会报错。
三、问题解决
根据上述,只要在geth_phy_release将phy_start(ndev->phydev)有没有正常执行区分开来,就可以轻松把问题解决,增加phy_start_flag标志位。
 修改如下:
static int geth_open(struct net_device *ndev)
{	
	... ...
	int phy_start_flag = 0;
	... ... 
	if (ndev->phydev)
	{
		phy_start(ndev->phydev);
		phy_start_flag = 1;
	}
	... ...
desc_err:
	geth_phy_release(ndev, phy_start_flag);
	... ...
}
static int geth_phy_release(struct net_device *ndev, int phy_start_flag)
{
	... ... 
	// /* Stop and disconnect the PHY */
	if (phydev && phy_start_flag)
		phy_stop(phydev);
	 ... ...
}












![[期末网页作业]-小米官网(html+css+js)](https://img-blog.csdnimg.cn/2427fd4b89e840c5b4d1bb9992762837.png)






