网络服务(3)——以太网phy的识别加载(RK3399)

这篇博客详细介绍了Linux环境下网络驱动的初始化过程,特别是针对rk_gmac-dwmacfe300000设备的PHY连接。驱动在启动时尝试与PHY设备进行通信,读取并显示了PHY的ID和其他关键信息。当PHY设备不存在时,驱动给出了相应的错误提示。文章还展示了sysfs接口下与PHY设备相关的文件内容,以及驱动注册和PHY设备扫描的流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

初始化信息

phy正常连接

log信息

[    1.279600] rk_gmac-dwmac fe300000.ethernet: clock input or output? (input).
[    1.280239] rk_gmac-dwmac fe300000.ethernet: TX delay(0x28).
[    1.280746] rk_gmac-dwmac fe300000.ethernet: RX delay(0x11).
[    1.281275] rk_gmac-dwmac fe300000.ethernet: integrated PHY? (no).
[    1.281991] rk_gmac-dwmac fe300000.ethernet: cannot get clock clk_mac_speed
[    1.282620] rk_gmac-dwmac fe300000.ethernet: clock input from PHY
[    1.288166] rk_gmac-dwmac fe300000.ethernet: init for RGMII
[    1.288783] stmmac - user ID: 0x10, Synopsys ID: 0x35
[    1.289240]  Ring mode enabled
[    1.289512]  DMA HW capability register supported
[    1.289911]  Normal descriptors
[    1.290220]  RX Checksum Offload Engine supported (type 2)
[    1.290717]  TX Checksum insertion supported
[    1.291093]  Wake-Up On Lan supported
[    1.291463]  Enable RX Mitigation via HW Watchdog Timer
[    1.356532] libphy: stmmac: probed
[    1.356845] eth%d: PHY ID 001cc915 at 0 IRQ POLL (stmmac-0:00) active
[    1.357428] eth%d: PHY ID 001cc915 at 1 IRQ POLL (stmmac-0:01)

sysfs接口信息

[root@rk3399:/]# cat /sys/devices/platform/fe300000.ethernet/mdio_bus/stmmac-0/
device/       stmmac-0:00/  subsystem/
power/        stmmac-0:01/  uevent
[root@rk3399:/]# cat /sys/devices/platform/fe300000.ethernet/mdio_bus/stmmac-0/s
tmmac-0:00/phy_id 
0x001cc915
[root@rk3399:/]# cat /sys/devices/platform/fe300000.ethernet/mdio_bus/stmmac-0/s
tmmac-0:00/phy_registers 
 0: 0x1140
 1: 0x796d
 2: 0x1c
 3: 0xc915
 4: 0x1e1
 5: 0xc1e1
 6: 0xd
 7: 0x2001
 8: 0x6001
 9: 0x300
10: 0x3800
11: 0x0
12: 0x0
13: 0x0
14: 0x0
15: 0x3000
16: 0x16e
17: 0xad42
18: 0x9f01
19: 0x6c52
20: 0x8040
21: 0x1006
22: 0x4100
23: 0x2100
24: 0x0
25: 0x8c00
26: 0x40
27: 0x106
28: 0x217c
29: 0x8038
30: 0x123
31: 0x0

去掉phy芯片

log信息

[    1.286877] rk_gmac-dwmac fe300000.ethernet: clock input or output? (input).
[    1.287517] rk_gmac-dwmac fe300000.ethernet: TX delay(0x28).
[    1.288023] rk_gmac-dwmac fe300000.ethernet: RX delay(0x11).
[    1.288552] rk_gmac-dwmac fe300000.ethernet: integrated PHY? (no).
[    1.289270] rk_gmac-dwmac fe300000.ethernet: cannot get clock clk_mac_speed
[    1.289899] rk_gmac-dwmac fe300000.ethernet: clock input from PHY
[    1.295453] rk_gmac-dwmac fe300000.ethernet: init for RGMII
[    1.296059] stmmac - user ID: 0x10, Synopsys ID: 0x35
[    1.296515]  Ring mode enabled
[    1.296788]  DMA HW capability register supported
[    1.297186]  Normal descriptors
[    1.297503]  RX Checksum Offload Engine supported (type 2)
[    1.297992]  TX Checksum insertion supported
[    1.298376]  Wake-Up On Lan supported
[    1.298736]  Enable RX Mitigation via HW Watchdog Timer
[    1.364025] libphy: stmmac: probed
[    1.364343] eth%d: No PHY found

驱动识别过程

驱动文件

kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
kernel/drivers/net/phy/phy_device.c
kernel/drivers/net/phy/mdio_bus.c
kernel/include/linux/phy.h
kernel/drivers/net/ethernet/stmicro/stmmac/stmmac.h
kernel/include/linux/netdevice.h
#define PHY_MAX_ADDR     32
#define SET_NETDEV_DEV(net, pdev)       ((net)->dev.parent = (pdev))
#define mdiobus_register(bus) __mdiobus_register(bus, THIS_MODULE)
stmmac_mdio_register(struct net_device *ndev)		//注册mdio总线,配置总线参数,配置phydev中断属性
	mdiobus_register(new_bus);						//注册mii_bus,在总线上扫描PHY_ADDR 0到31是否有对应的phydev
		mdiobus_scan(bus, i);						//按照传递的addr数值,获取总线上是否有p对应的phydev,如果有使用phy_device_register函数进行注册
			get_phy_device(bus, addr, false);
				get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids);		//按照传递的addr数值读取对应addr上phy设备的id,如果有对应的设备会返回phy设备的id,否则返回0xffffffff
				phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);
			phy_device_register(phydev);
	
/**
 * stmmac_mdio_register
 * @ndev: net device structure
 * Description: it registers the MII bus
 */
int stmmac_mdio_register(struct net_device *ndev)
{
        int err = 0;
        struct mii_bus *new_bus;
        int *irqlist;
        struct stmmac_priv *priv = netdev_priv(ndev);
        struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
        int addr, found;

        if (!mdio_bus_data)
                return 0;

        new_bus = mdiobus_alloc();
        if (new_bus == NULL)
                return -ENOMEM;

        if (mdio_bus_data->irqs) {
                irqlist = mdio_bus_data->irqs;
        } else {
                for (addr = 0; addr < PHY_MAX_ADDR; addr++)
                        priv->mii_irq[addr] = PHY_POLL;
                irqlist = priv->mii_irq;
        }

#ifdef CONFIG_OF
        if (priv->device->of_node)
                mdio_bus_data->reset_gpio = -1;
#endif

        new_bus->name = "stmmac";
        new_bus->read = &stmmac_mdio_read;
        new_bus->write = &stmmac_mdio_write;
        new_bus->reset = &stmmac_mdio_reset;
        snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
                 new_bus->name, priv->plat->bus_id);
        new_bus->priv = ndev;
        new_bus->irq = irqlist;
        new_bus->phy_mask = mdio_bus_data->phy_mask;
        new_bus->parent = priv->device;
        err = mdiobus_register(new_bus);
        if (err != 0) {
                pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
                goto bus_register_fail;
        }

        found = 0;
        for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
                struct phy_device *phydev = new_bus->phy_map[addr];
                if (phydev) {
                        int act = 0;
                        char irq_num[4];
                        char *irq_str;

                        /*
                         * If an IRQ was provided to be assigned after
                         * the bus probe, do it here.
                         */
                        if ((mdio_bus_data->irqs == NULL) &&
                            (mdio_bus_data->probed_phy_irq > 0)) {
                                irqlist[addr] = mdio_bus_data->probed_phy_irq;
                                phydev->irq = mdio_bus_data->probed_phy_irq;
                        }

                        /*
                         * If we're going to bind the MAC to this PHY bus,
                         * and no PHY number was provided to the MAC,
                         * use the one probed here.
                         */
                        if (priv->plat->phy_addr == -1)
                                priv->plat->phy_addr = addr;

                        act = (priv->plat->phy_addr == addr);
                        switch (phydev->irq) {
                        case PHY_POLL:
                                irq_str = "POLL";
                                break;
                        case PHY_IGNORE_INTERRUPT:
                                irq_str = "IGNORE";
                                break;
                        default:
                                sprintf(irq_num, "%d", phydev->irq);
                                irq_str = irq_num;
                                break;
                        }
                        pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
                                ndev->name, phydev->phy_id, addr,
                                irq_str, dev_name(&phydev->dev),
                                act ? " active" : "");
                        found = 1;
                }
        }

        if (!found) {
                pr_warn("%s: No PHY found\n", ndev->name);
                mdiobus_unregister(new_bus);
                mdiobus_free(new_bus);
                return -ENODEV;
        }

        priv->mii = new_bus;

        return 0;

bus_register_fail:
        mdiobus_free(new_bus);
        return err;
}
/**
 * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
 * @bus: target mii_bus
 * @owner: module containing bus accessor functions
 *
 * Description: Called by a bus driver to bring up all the PHYs
 *   on a given bus, and attach them to the bus. Drivers should use
 *   mdiobus_register() rather than __mdiobus_register() unless they
 *   need to pass a specific owner module.
 *
 * Returns 0 on success or < 0 on error.
 */
 int __mdiobus_register(struct mii_bus *bus, struct module *owner)

struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)

/**
 * get_phy_device - reads the specified PHY device and returns its @phy_device
 *                  struct
 * @bus: the target MII bus
 * @addr: PHY address on the MII bus
 * @is_c45: If true the PHY uses the 802.3 clause 45 protocol
 *
 * Description: Reads the ID registers of the PHY at @addr on the
 *   @bus, then allocates and returns the phy_device to represent it.
 */
struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)

/**
 * phy_device_register - Register the phy device on the MDIO bus
 * @phydev: phy_device structure to be added to the MDIO bus
 */
int phy_device_register(struct phy_device *phydev)

struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
                                     bool is_c45,
                                     struct phy_c45_device_ids *c45_ids)
### RK3588 设备通过网线共享笔记本网络时 &#39;网络连接激活失败&#39; 的原因分析与解决方案 在网络共享场景下,RK3588 开发板作为客户端尝试通过有线方式接入由笔记本创建的共享网络时出现问题,可能的原因涉及多个层面,包括硬件配置、操作系统设置以及网络协议适配等方面。 #### 1. **硬件层面上的可能性** 如果开发板上的网卡驱动未正确加载或者存在兼容性问题,则可能导致无法正常识别或启用网络接口。例如,在某些情况下,AP6256 Wi-Fi 和 Bluetooth 模块虽然主要负责无线通信,但如果其底层固件存在问题也可能间接影响到整个系统的稳定性[^1]。对于以太网部分来说,需确认所使用的 RJ45 接口及其对应的 PHY 芯片是否被当前 Linux 内核版本良好支持。 #### 2. **操作系统的网络管理服务冲突** 现代 Linux 发行版通常会依赖 NetworkManager 或 systemd-networkd 来处理动态 IP 地址获取等功能。当两者同时运行并试图控制相同的物理设备时容易引发混乱状况——即所谓的“竞争条件”。具体表现为即使 DHCP 客户端看似已发出请求却始终得不到服务器回应的现象。针对这种情况可以考虑停用其中一个服务试试看效果如何: ```bash sudo systemctl stop NetworkManager.service sudo systemctl disable NetworkManager.service ``` 另外还需注意检查 `/etc/network/interfaces` 文件中的静态配置项是否会干扰自动协商过程。 #### 3. **IP地址范围重叠引起的路由错误** 假设主机(此处指代提供互联网访问权限的那个节点)分配给子网成员们的 IPv4 地址段正好与其上游 ISP 所授予的一致的话,那么势必会造成逻辑上的矛盾进而阻止数据包按照预期路径转发出去。因此建议重新规划内部 LAN 使用私有的 RFC1918 地址池之一来规避此类风险[^4]: - `10.0.0.0/8` - `172.16.0.0/12` - `192.168.0.0/16` 与此同时也要记得调整 NAT 参数使之匹配新的拓扑结构变化情况下的需求。 #### 4. **防火墙规则阻挡必要的流量传输** 无论是 Windows Defender Firewall 还是 iptables/ufw 等工具都可能存在预设策略不允许外部实体未经许可便随意发起连接的行为发生。所以有必要临时关闭这些防护机制看看能否解决问题然后再逐步恢复至更安全的状态下去运作: Windows 平台命令示例: ```powershell netsh advfirewall set allprofiles state off ``` Linux 方面则执行如下指令即可实现相同目的: ```bash sudo ufw disable sudo iptables -P INPUT ACCEPT && sudo iptables -F ``` 最后提醒一点就是务必核实一下 MTU 值设定得是否合理因为过高的数值可能会引起分片丢失从而降低吞吐量甚至完全断开链接[^2]. --- ### 实施上述措施后的验证步骤 完成以上各项排查之后应该再次测试目标功能是否恢复正常工作状态。可以通过 ping 测试远程公网 DNS 解析器(比如 Google Public DNS @8.8.8.8)的方式初步判断连通性质量的好坏程度;接着再打开浏览器输入任意知名网站域名观察页面渲染速度以此衡量整体性能指标达成水平。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值