phy state machine 与 rate --- linux kernel 欣赏

本文解析了在Linux内核中,PHY设备状态变化时所触发的处理流程。重点介绍了phy_link_change和macb_handle_link_change两个核心函数,展示了如何通过这些函数更新网络设备的状态,并解释了在不同状态下对网络设备进行配置的具体细节。

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

/*    
 *    当你使用 ifconfig ethx up、down 时, 这个函数就被执行到了. 知道了它的执行时机了吧 😄
 *    比如 : PHY_FORCING -> PHY_RUNNING 切换的时候. 
 * 
 *    phy 的12种状态中的4种在phy状态机中是归纳为同一种处理的. 
 *    state 叠加了 ?  不论你观不观测它, 它都是4态合一, TMD 量子力学也只有两态吧 😄😄
 *    这几天著名的双缝干涉实验看的有点多 .... 😂
 */
static void phy_link_change(struct phy_device *phydev, bool up, bool do_carrier)
{
   /*
    *    核心动作来了.
    *    为了 mac 与 phy 的绑定, kernel 准备了很多. 用兵一时. 好了,这里就拿出mac来了.
    *    拿出mac仅仅是为了执行netif_carrier_xx的需要. 在核心函数 如 macb_handle_link_change()
    *    也仅仅是为了获取到 phy. 
	*/
	struct net_device *netdev = phydev->attached_dev;
	
   /*
    *    这是一个布尔值. 要明白这个值的用意,就必须要理解 phy的状态切换.
	*/
	if (do_carrier) {
		if (up)
			netif_carrier_on(netdev);
		else
			netif_carrier_off(netdev);
	}
	phydev->adjust_link(netdev);
}
static void macb_handle_link_change(struct net_device *dev)
{
	struct macb *bp = netdev_priv(dev);
	struct phy_device *phydev = dev->phydev;
	unsigned long flags;
	int status_change = 0;

	spin_lock_irqsave(&bp->lock, flags);

	if (phydev->link) {
		if ((bp->speed != phydev->speed) ||
		    (bp->duplex != phydev->duplex)) {
			u32 reg;

			reg = macb_readl(bp, NCFGR);
			reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
			if (macb_is_gem(bp))
				reg &= ~GEM_BIT(GBE);

			if (phydev->duplex)
				reg |= MACB_BIT(FD);
			if (phydev->speed == SPEED_100)
				reg |= MACB_BIT(SPD);
			if (phydev->speed == SPEED_1000 &&
			    bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
				reg |= GEM_BIT(GBE);

			macb_or_gem_writel(bp, NCFGR, reg);

			bp->speed = phydev->speed;
			bp->duplex = phydev->duplex;
			status_change = 1;
		}
	}

	if (phydev->link != bp->link) {
		if (!phydev->link) {
			bp->speed = 0;
			bp->duplex = -1;
		}
		bp->link = phydev->link;

		status_change = 1;
	}

	spin_unlock_irqrestore(&bp->lock, flags);

	if (status_change) {
		if (phydev->link) {
			/* Update the TX clock rate if and only if the link is
			 * up and there has been a link change.
			 */
			macb_set_tx_clk(bp->tx_clk, phydev->speed, dev);

			netif_carrier_on(dev);
			netdev_info(dev, "link up (%d/%s)\n",
				    phydev->speed,
				    phydev->duplex == DUPLEX_FULL ?
				    "Full" : "Half");
		} else {
			netif_carrier_off(dev);
			netdev_info(dev, "link down\n");
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值