三 Linux 网络驱动-MAC、PHY层驱动框架( 七 )


1static int of_mdiobus_register_phy(struct mii_bus *mdio,struct device_node *child,2u32 addr)3 {4struct phy_device *phy;5bool is_c45;6int rc;7u32 phy_id;8 9is_c45 = of_device_is_compatible(child,10"ethernet-phy-ieee802.3-c45");1112if (!is_c45 && !of_get_phy_id(child, &phy_id))13phy = phy_device_create(mdio, addr, phy_id, 0, NULL);14else15phy = get_phy_device(mdio, addr, is_c45);16if (!phy || IS_ERR(phy))17return 1;1819rc = irq_of_parse_and_map(child, 0);20if (rc > 0) {21phy->irq = rc;22if (mdio->irq)23mdio->irq[addr] = rc;24} else {25if (mdio->irq)26phy->irq = mdio->irq[addr];27}2829/* Associate the OF node with the device structure so it30* can be looked up later */31of_node_get(child);32phy->dev.of_node = child;3334/* All data is now stored in the phy struct;35* register it */36rc = phy_device_register(phy);37if (rc) {38phy_device_free(phy);39of_node_put(child);40return 1;41}4243dev_dbg(&mdio->dev, "registered phy %s at address %i\n",44child->name, addr);4546return 0;47 }
第 9 行 , 使用函数ble 检查 PHY节点的属性是否为“-phy-.3-c45” , 如果是的话要做其他的处理 , 本章节我们设置的属性为“-phy-.3-c22” 。
第 15 行 , 调用函数获取 PHY 设备 , 此函数里面会调用来创建一个设备并返回.
第 19 行 , 获取 PHY 芯片的中断信息 , 本章节并未用到 。
第 36 行 , 调用函数向 Linux 内核注册 PHY 设备 。
从上面的分析可以看出 , 向 Linux 内核注册 MDIO 总线的时候也会同时向 Linux 内核注册 PHY 设备 , 流程如图所示:
注册 MIDO 总线的时候会从设备树中查找 PHY 设备 , 然后通过函数向 内核注册 PHY 设备 , 接下来我们就来学习一下 PHY 子系统 。
3、 函数简析
卸载 I. 网络驱动的时候函数就会执行 , 函数内容如下所示:
1 static int fec_drv_remove(struct platform_device *pdev)2 {3struct net_device *ndev = platform_get_drvdata(pdev);4struct fec_enet_private *fep = netdev_priv(ndev);5 6cancel_delayed_work_sync(&fep->time_keep);7cancel_work_sync(&fep->tx_timeout_work);8unregister_netdev(ndev);9fec_enet_mii_remove(fep);10if (fep->reg_phy)11regulator_disable(fep->reg_phy);12if (fep->ptp_clock)13ptp_clock_unregister(fep->ptp_clock);14of_node_put(fep->phy_node);15free_netdev(ndev);1617return 0;18 }
第 8 行 , 调用函数注销前面注册的。
第 9 行 , 调用函数来移除掉 MDIO 总线相关的内容 , 此函数会调用来注销掉  , 并且通过函数释放掉
第 15 行 , 调用函数释放掉前面申请的。
4、 操作集
函数设置了网卡驱动的操作集为  ,  内 容如下:
1 static const struct net_device_ops fec_netdev_ops = {2.ndo_open = fec_enet_open,3.ndo_stop = fec_enet_close,4.ndo_start_xmit = fec_enet_start_xmit,5.ndo_select_queue = fec_enet_select_queue,6.ndo_set_rx_mode = set_multicast_list,7.ndo_change_mtu = eth_change_mtu,8.ndo_validate_addr = eth_validate_addr,9.ndo_tx_timeout = fec_timeout,10.ndo_set_mac_address = fec_set_mac_address,11.ndo_do_ioctl = fec_enet_ioctl,12 #ifdef CONFIG_NET_POLL_CONTROLLER13.ndo_poll_controller = fec_poll_controller,14 #endif15.ndo_set_features = fec_set_features,16 };
函数简析
打开一个网卡的时候函数就会执行 , 函数源码如下所示(限于篇幅原因 , 有 省略):
示例代码 fec_enet_open 函数1 static int fec_enet_open(struct net_device *ndev)2 {3struct fec_enet_private *fep = netdev_priv(ndev);4const struct platform_device_id *id_entry =5platform_get_device_id(fep->pdev);6int ret;7 8pinctrl_pm_select_default_state(&fep->pdev->dev);9ret = fec_enet_clk_enable(ndev, true);10if (ret)11return ret;1213/* I should reset the ring buffers here, but I don't yet know14* a simple way to do that.15*/1617ret = fec_enet_alloc_buffers(ndev);18if (ret)19goto err_enet_alloc;2021/* Init MAC prior to mii bus probe */22fec_restart(ndev);2324/* Probe and connect to PHY when open the interface */25ret = fec_enet_mii_probe(ndev);26if (ret)27goto err_enet_mii_probe;2829napi_enable(&fep->napi);30phy_start(fep->phy_dev);31netif_tx_start_all_queues(ndev);32......4748return 0;4950err_enet_mii_probe:51fec_enet_free_buffers(ndev);52err_enet_alloc:53fep->miibus_up_failed = true;54if (!fep->mii_bus_share)55pinctrl_pm_select_sleep_state(&fep->pdev->dev);56return ret;57 }