ethtool網路工具內核解析流程

##內核ethtool工具源碼解析

###背景

用戶態使用ethtool工具設置網口的模式(速率,雙工,協商)時,發現設置的內容和讀取的內容是不一
致的,以此問題爲出發點,跟蹤下內容ethtool的處理流程。
用戶態設置網口模式的方法是 linux c通過socket打開網口,封裝ethtool_cmd和ifreq結構體,然後ioctl逐步陷入內核中。

###用戶態代碼

struct ifreq ifr;
struct ethtool_cmd *ethtool = NULL;

strncpy(ifr.ifr_name, priv_data->eth_name, ethlen);
ifr.ifr_data = (void *)ethtool;
ethtool->cmd = ETHTOOL_SSET;
ethtool->speed = mode->speed;
ethtool->autoneg = mode->autoneg;
ethtool->duplex = mode->duplex;
ethtool->phy_address = phy_addr;
ethtool->advertising = MII_BCMR_ADVERTIS;


ret = ioctl(priv_data->mac_fd, SIOCETHTOOL, &ifr);

###內核解析流程

[  133.060870] [<ffff00000866124c>] phy_ethtool_sset+0x24/0x130
[  133.066528] [<ffff000008851348>] dpa_set_settings+0x64/0x90
[  133.072099] [<ffff0000089e6064>] ethtool_set_settings+0x104/0x110
[  133.078190] [<ffff00000887d65c>] dev_ethtool+0x17fc/0x1bb0
[  133.083674] [<ffff00000889188c>] dev_ioctl+0x31c/0x608
[  133.088809] [<ffff000008852fc0>] sock_do_ioctl+0x70/0x88
[  133.094119] [<ffff0000088546f8>] sock_ioctl+0x260/0x360
[  133.099342] [<ffff0000082624f8>] do_vfs_ioctl+0xb0/0x830
[  133.104651] [<ffff000008262d0c>] SyS_ioctl+0x94/0xa8
[  133.109612] [<ffff000008083b00>] el0_svc_naked+0x34/0x38


static int __cold dpa_set_settings(struct net_device *net_dev,
		struct ethtool_cmd *et_cmd)
{
	int			 _errno;
	struct dpa_priv_s	*priv;

	priv = netdev_priv(net_dev);

	if (priv->mac_dev == NULL) {
		netdev_info(net_dev, "This is a MAC-less interface\n");
		return -ENODEV;
	}
	if (unlikely(priv->mac_dev->phy_dev == NULL)) {
		netdev_err(net_dev, "phy device not initialized\n");
		return -ENODEV;
	}

	_errno = phy_ethtool_sset(priv->mac_dev->phy_dev, et_cmd);
	if (unlikely(_errno < 0))
		netdev_err(net_dev, "phy_ethtool_sset() = %d\n", _errno);

	return _errno;
}




int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
{
dump_stack();
printk("error phy_ethtool_sset cmd speed high %d %d\n", cmd->speed_hi, cmd->speed);
u32 speed = ethtool_cmd_speed(cmd);

if (cmd->phy_address != phydev->mdio.addr)
	return -EINVAL;

/* We make sure that we don't pass unsupported values in to the PHY */
cmd->advertising &= phydev->supported;

/* Verify the settings we care about. */
if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
	return -EINVAL;

if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
	return -EINVAL;
printk("error phy_ethtool_sset 111\n");
if (cmd->autoneg == AUTONEG_DISABLE &&
    ((speed != SPEED_1000 &&
      speed != SPEED_100 &&
      speed != SPEED_10) ||
     (cmd->duplex != DUPLEX_HALF &&
      cmd->duplex != DUPLEX_FULL)))    /*從這裏可以看出,1) 如果自協商關閉,2) 速度也不是10 100 1000M或者雙工模式不是全或者半的話,返回錯誤 */
	return -EINVAL;

phydev->autoneg = cmd->autoneg;

phydev->speed = speed;

phydev->advertising = cmd->advertising;

if (AUTONEG_ENABLE == cmd->autoneg)
	phydev->advertising |= ADVERTISED_Autoneg;
else
	phydev->advertising &= ~ADVERTISED_Autoneg;

phydev->duplex = cmd->duplex;

phydev->mdix = cmd->eth_tp_mdix_ctrl;

printk("error phy_ethtool_sset 222\n");
/* Restart the PHY */
phy_start_aneg(phydev);

return 0;
}


static int phy_start_aneg_priv(struct phy_device *phydev, bool sync)
{
bool trigger = 0;
int err;

if (!phydev->drv)
	return -EIO;

mutex_lock(&phydev->lock);

if (AUTONEG_DISABLE == phydev->autoneg)
	phy_sanitize_settings(phydev);

/* Invalidate LP advertising flags */
phydev->lp_advertising = 0;

printk("error phy_start_aneg_priv config_aneg %pf\n", phydev->drv->config_aneg);
err = phydev->drv->config_aneg(phydev);  /*這裏是關鍵,這個地方是註冊的網卡對應的配置驅動,由於看代碼找這個函數的實現比較麻煩,索性之間用上面printk將這個函數指針的名字給打印出來了。比較簡便快捷。*/
if (err < 0) 
	goto out_unlock;

if (phydev->state != PHY_HALTED) {
	if (AUTONEG_ENABLE == phydev->autoneg) {
		phydev->state = PHY_AN;
		phydev->link_timeout = PHY_AN_TIMEOUT;
	} else {
		phydev->state = PHY_FORCING;
		phydev->link_timeout = PHY_FORCE_TIMEOUT;
	}
}

/* Re-schedule a PHY state machine to check PHY status because
 * negotiation may already be done and aneg interrupt may not be
 * generated.
 */
if (phy_interrupt_is_valid(phydev) && (phydev->state == PHY_AN)) {
	err = phy_aneg_done(phydev);
	if (err > 0) {
		trigger = true;
		err = 0;
	}
}

out_unlock:
	mutex_unlock(&phydev->lock);

	if (trigger)
		phy_trigger_machine(phydev, sync);

	return err;
}

根據上面printk打印出來的函數名字發現,這個是一個ethtool工具對應的函數集合,這個集合中定義了  

多種處理函數,分別對應於用戶態的不同需求。如下所示:

const struct ethtool_ops dpa_ethtool_ops = {
.get_settings = dpa_get_settings,
.set_settings = dpa_set_settings,
.get_drvinfo = dpa_get_drvinfo,
.get_msglevel = dpa_get_msglevel,
.set_msglevel = dpa_set_msglevel,
.nway_reset = dpa_nway_reset,
.get_pauseparam = dpa_get_pauseparam,
.set_pauseparam = dpa_set_pauseparam,
.self_test = NULL, /* TODO invoke the cold-boot unit-test? */
.get_link = ethtool_op_get_link,
.get_eee = dpa_get_eee,
.set_eee = dpa_set_eee,
.get_sset_count = dpa_get_sset_count,
.get_ethtool_stats = dpa_get_ethtool_stats,
.get_strings = dpa_get_strings,
#ifdef CONFIG_PM
	.get_wol = dpa_get_wol,
	.set_wol = dpa_set_wol,
#endif
};

接着往下看,對於本例而言,走得是第二個函數 dpa_set_settings。
static int __cold dpa_set_settings(struct net_device *net_dev,
struct ethtool_cmd *et_cmd)
{
int _errno;
struct dpa_priv_s *priv;

	priv = netdev_priv(net_dev);

	if (priv->mac_dev == NULL) {
		netdev_info(net_dev, "This is a MAC-less interface\n");
		return -ENODEV;
	}
	if (unlikely(priv->mac_dev->phy_dev == NULL)) {
		netdev_err(net_dev, "phy device not initialized\n");
		return -ENODEV;
	}

	_errno = phy_ethtool_sset(priv->mac_dev->phy_dev, et_cmd);
	if (unlikely(_errno < 0))
		netdev_err(net_dev, "phy_ethtool_sset() = %d\n", _errno);

	return _errno;
}


phy_ethtool_sset調用了函數phy_start_aneg_priv,其實現如下。 比較關鍵的一行是err = phydev->drv->config_aneg(phydev); 其實就是調用了函數genphy_config_aneg對phy進行設置。


static int phy_start_aneg_priv(struct phy_device *phydev, bool sync)
{
bool trigger = 0;
int err;

if (!phydev->drv)
	return -EIO;

mutex_lock(&phydev->lock);

if (AUTONEG_DISABLE == phydev->autoneg)
	phy_sanitize_settings(phydev);

/* Invalidate LP advertising flags */
phydev->lp_advertising = 0;

printk("error phy_start_aneg_priv config_aneg %pf\n", phydev->drv->config_aneg);
err = phydev->drv->config_aneg(phydev);
if (err < 0)
	goto out_unlock;

if (phydev->state != PHY_HALTED) {
	if (AUTONEG_ENABLE == phydev->autoneg) {
		phydev->state = PHY_AN;
		phydev->link_timeout = PHY_AN_TIMEOUT;
	} else {
		phydev->state = PHY_FORCING;
		phydev->link_timeout = PHY_FORCE_TIMEOUT;
	}
}

/* Re-schedule a PHY state machine to check PHY status because
 * negotiation may already be done and aneg interrupt may not be
 * generated.
 */
if (phy_interrupt_is_valid(phydev) && (phydev->state == PHY_AN)) {
	err = phy_aneg_done(phydev);
	if (err > 0) {
		trigger = true;
		err = 0;
	}
}

out_unlock:
	mutex_unlock(&phydev->lock);

	if (trigger)
		phy_trigger_machine(phydev, sync);

	return err;
}

該函數比較關鍵,最後對網卡模式相關寄存器的設置從這裏開始,也就是這裏開始真正的操作硬件了。
如果設置的自協商模式,那麼,網卡會重新開始自協商。如果不是,就開始按照用戶的設置進行強制修改網卡寄存器BMCR。

int genphy_config_aneg(struct phy_device *phydev)
{
int err, changed;
dump_stack();
changed = genphy_config_eee_advert(phydev);

if (AUTONEG_ENABLE != phydev->autoneg)
	return genphy_setup_forced(phydev);   //如果非自協商模式,那麼強制根據用戶輸入寄存器。

err = genphy_config_advert(phydev);
if (err < 0) /* error */
	return err;

changed |= err;

if (changed == 0) {
	/* Advertisement hasn't changed, but maybe aneg was never on to
	 * begin with?  Or maybe phy was isolated?
	 */
	int ctl = phy_read(phydev, MII_BMCR);

	if (ctl < 0)
		return ctl;

	if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
		changed = 1; /* do restart aneg */
}

/* Only restart aneg if we are advertising something different
 * than we were before.
 */
if (changed > 0)
	return genphy_restart_aneg(phydev);

return 0;
}


/*強制設置網卡模式,裏面主要調用了phy_read和phy_write,這兩個函數都是通過mdio總線對phy進行讀寫。*/
int genphy_setup_forced(struct phy_device *phydev)
{
	int ctl = phy_read(phydev, MII_BMCR);

	ctl &= BMCR_LOOPBACK | BMCR_ISOLATE | BMCR_PDOWN;
	phydev->pause = 0;
	phydev->asym_pause = 0;

	if (SPEED_1000 == phydev->speed)
		ctl |= BMCR_SPEED1000;
	else if (SPEED_100 == phydev->speed)
		ctl |= BMCR_SPEED100;

	if (DUPLEX_FULL == phydev->duplex)
		ctl |= BMCR_FULLDPLX;

	return phy_write(phydev, MII_BMCR, ctl);
}

上述函數中的phy_read和phy_write函數實現方式均是通過mdio總線的方式對phy的寄存器進行讀寫,這個是網卡的硬件結構決定的,mdio總線是mac對phy管理的通道。

通過打印,可以查看出phy_read內部調用的函數是:xgmac_mdio_read。具體不在往下研究了。

設置爲自協商關閉時的回溯如下:

[  247.036800] [<ffff00000808aae8>] dump_backtrace+0x0/0x270
[  247.042196] [<ffff00000808af6c>] show_stack+0x24/0x30
[  247.047245] [<ffff0000084a8fc8>] dump_stack+0xa8/0xd0
[  247.052293] [<ffff000008663284>] genphy_setup_forced+0x44/0xa0
[  247.058123] [<ffff000008663324>] genphy_config_aneg+0x44/0x1f8
[  247.063954] [<ffff000008661034>] phy_start_aneg_priv.part.4+0x5c/0x218
[  247.070480] [<ffff000008661350>] phy_ethtool_sset+0x120/0x130
[  247.076224] [<ffff000008851368>] dpa_set_settings+0x64/0x90
[  247.081794] [<ffff0000089e6078>] ethtool_set_settings+0xf8/0x104
[  247.087798] [<ffff00000887d6a4>] dev_ethtool+0x1824/0x1bb0
[  247.093281] [<ffff0000088918ac>] dev_ioctl+0x31c/0x608
[  247.098416] [<ffff000008852fe0>] sock_do_ioctl+0x70/0x88
[  247.103725] [<ffff000008854718>] sock_ioctl+0x260/0x360
[  247.108948] [<ffff0000082624f8>] do_vfs_ioctl+0xb0/0x830
[  247.114256] [<ffff000008262d0c>] SyS_ioctl+0x94/0xa8
[  247.119218] [<ffff000008083b00>] el0_svc_naked+0x34/0x38

###關鍵的數據結構

ethtool工具相關功能內核的處理函數集合,用戶態的ethtool設置或者獲取網卡的相關信息,都是下面這個函數集合在處理的。本文來自於內核文件 dpa_ethtool.c。不同網卡對應的函數集合不一樣。

const struct ethtool_ops dpa_ethtool_ops = {
.get_settings = dpa_get_settings,
.set_settings = dpa_set_settings,
.get_drvinfo = dpa_get_drvinfo,
.get_msglevel = dpa_get_msglevel,
.set_msglevel = dpa_set_msglevel,
.nway_reset = dpa_nway_reset,
.get_pauseparam = dpa_get_pauseparam,
.set_pauseparam = dpa_set_pauseparam,
.self_test = NULL, /* TODO invoke the cold-boot unit-test? */
.get_link = ethtool_op_get_link,
.get_eee = dpa_get_eee,
.set_eee = dpa_set_eee,
.get_sset_count = dpa_get_sset_count,
.get_ethtool_stats = dpa_get_ethtool_stats,
.get_strings = dpa_get_strings,
#ifdef CONFIG_PM
	.get_wol = dpa_get_wol,
	.set_wol = dpa_set_wol,
#endif
};

###問題
無論用戶態網速設置爲多少(自協商關閉,全雙工開啓),在內核中均會被改爲10M 半雙工,經過多次家打印,發現改的地方是如下的代碼:

static void phy_sanitize_settings(struct phy_device *phydev)
{
	u32 features = phydev->supported;
	unsigned int idx;
    printk("error feature %d\n", features);
    print_setting();
    
	/* Sanitize settings based on PHY capabilities */
	if ((features & SUPPORTED_Autoneg) == 0)
		phydev->autoneg = AUTONEG_DISABLE;
    printk("error phy_sanitize_settings phydev speed %d dup %d\n", phydev->speed, phydev->duplex);
	idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
			features);
	phydev->speed = settings[idx].speed;
	phydev->duplex = settings[idx].duplex;
    printk("error phy_sanitize_settings phydev speed %d dup %d\n", phydev->speed, phydev->duplex);
}

phy_find_setting會查找表settings,當發現速度和雙工模式與表中匹配時,返回index。

static inline unsigned int phy_find_setting(int speed, int duplex)
{
	unsigned int idx = 0;

	while (idx < ARRAY_SIZE(settings) &&
	       (settings[idx].speed != speed || settings[idx].duplex != duplex))  /*speed 和 duplex全部相等時,纔會退出*/
		idx++;
    printk("error phy_find_setting idx %d MAX_NUM_SETTINGS %d\n", idx, MAX_NUM_SETTINGS);
	return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
}

這個函數是可以正確查找到index的。 問題是下面這個函數的第二個入參,從idx開始往後遍歷,settings[idx].setting 和入參features找不到一致的。

static inline unsigned int phy_find_valid(unsigned int idx, u32 features)
{
	while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
		idx++;
    printk("error phy_find_valid idx is %d\n", idx);
	return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
}

編寫函數將setting表中的setsting全部打印出來,

[   83.614561] error feature 25088          --- phy_find_valid 的第二個入參。
[   83.617705] error setting idx 0  524288
[   83.621544] error setting idx 1  262144
[   83.625382] error setting idx 2  4096
[   83.629048] error setting idx 3  32768
[   83.632799] error setting idx 4  131072
[   83.636638] error setting idx 5  32
[   83.640129] error setting idx 6  16
[   83.643620] error setting idx 7  8
[   83.647020] error setting idx 8  4
[   83.650424] error setting idx 9  2
[   83.653827] error setting idx 10 1

###SFUL單板實驗

[BSP]bspNet_EthModeGet "eth1",&aaa,&bbb,&ccc

CPU: 0 PID: 2430 Comm: appver Not tainted 4.9.115-rt93-EMBSYS-CGEL-6.1.R6 #2
Call Trace:
[c0000001df3ff6e0] [c000000000a37124] .dump_stack+0xac/0xec (unreliable)
[c0000001df3ff770] [c000000000627fc8] .phy_ethtool_gset+0x78/0xe0
[c0000001df3ff7e0] [c000000000a3c754] .dpa_get_settings+0x4c/0x98
[c0000001df3ff860] [c0000000008bdce0] .ethtool_get_settings+0x1a0/0x1e0
[c0000001df3ff970] [c0000000008c1884] .dev_ethtool+0x1294/0x2100
[c0000001df3ffa80] [c0000000008db9a0] .dev_ioctl+0x4c0/0x890
[c0000001df3ffb70] [c00000000088d740] .sock_do_ioctl+0x90/0xb0
[c0000001df3ffc00] [c00000000088e110] .sock_ioctl+0x2b0/0x3c0
[c0000001df3ffca0] [c0000000001f9bd4] .do_vfs_ioctl+0xc4/0x8a0
[c0000001df3ffd90] [c0000000001fa408] .SyS_ioctl+0x58/0xb0
[c0000001df3ffe30] [c000000000000698] system_call+0x38/0x108

 0 , 0x0
[BSP]aaa
	
 281474976710656000 , 0x3e8000000000000
[BSP]bbb

	 72057594037927936 , 0x100000000000000
[BSP]ccc

	 72057594037927936 , 0x100000000000000
[BSP]bsp_boot_sync,211: No need to sync boot.


[BSP]



[BSP]bspNet_EthModeSet "eth1",100,0,1
CPU: 0 PID: 2430 Comm: appver Not tainted 4.9.115-rt93-EMBSYS-CGEL-6.1.R6 #2
Call Trace:
[c0000001df3ff6e0] [c000000000a37124] .dump_stack+0xac/0xec (unreliable)
[c0000001df3ff770] [c000000000627fc8] .phy_ethtool_gset+0x78/0xe0
[c0000001df3ff7e0] [c000000000a3c754] .dpa_get_settings+0x4c/0x98
[c0000001df3ff860] [c0000000008bdce0] .ethtool_get_settings+0x1a0/0x1e0
[c0000001df3ff970] [c0000000008c1884] .dev_ethtool+0x1294/0x2100
[c0000001df3ffa80] [c0000000008db9a0] .dev_ioctl+0x4c0/0x890
[c0000001df3ffb70] [c00000000088d740] .sock_do_ioctl+0x90/0xb0
[c0000001df3ffc00] [c00000000088e110] .sock_ioctl+0x2b0/0x3c0
[c0000001df3ffca0] [c0000000001f9bd4] .do_vfs_ioctl+0xc4/0x8a0
[c0000001df3ffd90] [c0000000001fa408] .SyS_ioctl+0x58/0xb0
[c0000001df3ffe30] [c000000000000698] system_call+0x38/0x108
CPU: 0 PID: 2430 Comm: appver Not tainted 4.9.115-rt93-EMBSYS-CGEL-6.1.R6 #2
Call Trace:
[c0000001df3ff6d0] [c000000000a37124] .dump_stack+0xac/0xec (unreliable)
[c0000001df3ff760] [c000000000629404] .phy_ethtool_sset+0x24/0x180
[c0000001df3ff7f0] [c000000000a3c6c4] .dpa_set_settings+0x68/0xac
[c0000001df3ff870] [c0000000008bd888] .ethtool_set_settings+0x108/0x170
[c0000001df3ff970] [c0000000008c186c] .dev_ethtool+0x127c/0x2100
[c0000001df3ffa80] [c0000000008db9a0] .dev_ioctl+0x4c0/0x890
[c0000001df3ffb70] [c00000000088d740] .sock_do_ioctl+0x90/0xb0
[c0000001df3ffc00] [c00000000088e110] .sock_ioctl+0x2b0/0x3c0
[c0000001df3ffca0] [c0000000001f9bd4] .do_vfs_ioctl+0xc4/0x8a0
[c0000001df3ffd90] [c0000000001fa408] .SyS_ioctl+0x58/0xb0
[c0000001df3ffe30] [c000000000000698] system_call+0x38/0x108
error phy_ethtool_sset cmd speed high 0 100
error speed 100
error phy_ethtool_sset 111
error phy_ethtool_sset 222
error feature 25194
error setting idx 0  524288
error setting idx 1  262144
error setting idx 2  4096
error setting idx 3  32768
error setting idx 4  131072
error setting idx 5  32
error setting idx 6  16
error setting idx 7  8
error setting idx 8  4
error setting idx 9  2
error setting idx 10  1
error phy_sanitize_settings phydev speed 100 dup 1
error phy_find_setting idx 7 MAX_NUM_SETTINGS 11
error phy_find_valid idx is 7
error phy_sanitize_settings phydev speed 100 dup 1
error phy_start_aneg_priv config_aneg .genphy_config_aneg
CPU: 0 PID: 2430 Comm: appver Not tainted 4.9.115-rt93-EMBSYS-CGEL-6.1.R6 #2
Call Trace:
[c0000001df3ff590] [c000000000a37124] .dump_stack+0xac/0xec (unreliable)
[c0000001df3ff620] [c00000000062bbd4] .genphy_config_aneg+0x24/0x2f0
[c0000001df3ff6b0] [c000000000629060] .phy_start_aneg_priv.part.6+0x90/0x3e0
[c0000001df3ff760] [c000000000629548] .phy_ethtool_sset+0x168/0x180
[c0000001df3ff7f0] [c000000000a3c6c4] .dpa_set_settings+0x68/0xac
[c0000001df3ff870] [c0000000008bd888] .ethtool_set_settings+0x108/0x170
[c0000001df3ff970] [c0000000008c186c] .dev_ethtool+0x127c/0x2100
[c0000001df3ffa80] [c0000000008db9a0] .dev_ioctl+0x4c0/0x890
[c0000001df3ffb70] [c00000000088d740] .sock_do_ioctl+0x90/0xb0
[c0000001df3ffc00] [c00000000088e110] .sock_ioctl+0x2b0/0x3c0
[c0000001df3ffca0] [c0000000001f9bd4] .do_vfs_ioctl+0xc4/0x8a0
[c0000001df3ffd90] [c0000000001fa408] .SyS_ioctl+0x58/0xb0
[c0000001df3ffe30] [c000000000000698] system_call+0x38/0x108
bus mdio read is .xgmac_mdio_read
CPU: 0 PID: 2430 Comm: appver Not tainted 4.9.115-rt93-EMBSYS-CGEL-6.1.R6 #2
Call Trace:
[c0000001df3ff5a0] [c000000000a37124] .dump_stack+0xac/0xec (unreliable)
[c0000001df3ff630] [c00000000062baec] .genphy_setup_forced+0x4c/0x110
[c0000001df3ff6b0] [c000000000629060] .phy_start_aneg_priv.part.6+0x90/0x3e0
[c0000001df3ff760] [c000000000629548] .phy_ethtool_sset+0x168/0x180
[c0000001df3ff7f0] [c000000000a3c6c4] .dpa_set_settings+0x68/0xac
[c0000001df3ff870] [c0000000008bd888] .ethtool_set_settings+0x108/0x170
[c0000001df3ff970] [c0000000008c186c] .dev_ethtool+0x127c/0x2100
[c0000001df3ffa80] [c0000000008db9a0] .dev_ioctl+0x4c0/0x890
[c0000001df3ffb70] [c00000000088d740] .sock_do_ioctl+0x90/0xb0
[c0000001df3ffc00] [c00000000088e110] .sock_ioctl+0x2b0/0x3c0
[c0000001df3ffca0] [c0000000001f9bd4] .do_vfs_ioctl+0xc4/0x8a0
[c0000001df3ffd90] [c0000000001fa408] .SyS_ioctl+0x58/0xb0
[c0000001df3ffe30] [c000000000000698] system_call+0x38/0x108
error phy speed is 100 duplex 1
error MII_BMCR 0x2100

 0 , 0x0




appver中的結構可以正常的get和set的。

這樣看來,確實是SFUQ的板子有問題的,那麼

定時器一致讀phy的回溯。

[   33.007200] CPU: 0 PID: 70 Comm: kworker/0:1 Tainted: G           O    4.9.115-rt93-CGEL-V6.02.10.R2 #42
[   33.016682] Hardware name: LS1046A RDB Board (DT)
[   33.021383] Workqueue: events_power_efficient phy_state_machine
[   33.027305] Call trace:
[   33.029747] [<ffff00000808aae8>] dump_backtrace+0x0/0x270
[   33.035143] [<ffff00000808af6c>] show_stack+0x24/0x30
[   33.040192] [<ffff0000084aa008>] dump_stack+0xa8/0xd0
[   33.045242] [<ffff000008666110>] mdiobus_read+0x38/0x80
[   33.050464] [<ffff000008664a70>] genphy_read_status+0xb0/0x218
[   33.056295] [<ffff000008663188>] phy_state_machine+0x4c0/0x5a8
[   33.062126] [<ffff0000080ef338>] process_one_work+0x218/0x4e0
[   33.067869] [<ffff0000080ef658>] worker_thread+0x58/0x4b8
[   33.073266] [<ffff0000080f5d58>] kthread+0xd8/0xf0
[   33.078053] [<ffff000008083aa0>] ret_from_fork+0x10/0x30

dts mac

		ethernet@e0000 {     				/*這個就是mac*/  
			cell-index = <0x0>;
			compatible = "fsl,fman-memac";
			reg = <0xe0000 0x1000>;
			fsl,fman-ports = <0x14 0x15>;
			ptp-timer = <0x16>;
			pcsphy-handle = <0x17>;
			linux,phandle = <0x32>;
			phandle = <0x32>;
		};

eth2

		ethernet@2 {						  /*eth3*/  
			compatible = "fsl,dpa-ethernet";
			fsl,fman-mac = <0x34>;
			dma-coherent;
		};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章