Open
stmmac_open是在stmmac_netdev_ops结构体里的,这个ops在probe时就已经注册到了net_device结构体里,在网卡对于stmmac_open函数调用的时间我还不确定是否是在网卡link up时
下面看看stmmac_open函数,文件位置: drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
在open函数中主要完成了以下操作
-
连接到PHY,设置好合适的速率
-
申请、初始化dma 描述符资源和队列,在后面初始化网卡的dma 引擎时会将用到
-
初始化DMA
-
初始化MAC
-
申请、初始化中断资源
-
enable、start队列
下面来实际看看代码
static int stmmac_open(struct net_device *dev)
{struct stmmac_priv *priv = netdev_priv(dev);u32 chan;int ret;if (priv->hw->pcs != STMMAC_PCS_RGMII &&priv->hw->pcs != STMMAC_PCS_TBI &&priv->hw->pcs != STMMAC_PCS_RTBI) {ret = stmmac_init_phy(dev);if (ret) {netdev_err(priv->dev,"%s: Cannot attach to PHY (error: %d)\n",__func__, ret);return ret;}}/* Extra statistics */memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));priv->xstats.threshold = tc;priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);priv->rx_copybreak = STMMAC_RX_COPYBREAK;//分配描述符资源放到priv->rx_queue[queue] priv->tx_queue[queue]ret = alloc_dma_desc_resources(priv);if (ret < 0) {netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n",__func__);goto dma_desc_error;}//初始化接收和发送描述符资源队列ret = init_dma_desc_rings(dev, GFP_KERNEL);if (ret < 0) {netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n",__func__);goto init_error;}//初始化DMA、MACret = stmmac_hw_setup(dev, true);if (ret < 0) {netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);goto init_error;}stmmac_init_tx_coalesce(priv);//if (dev->phydev)phy_start(dev->phydev);/* Request the IRQ lines */ret = request_irq(dev->irq, stmmac_interrupt,IRQF_SHARED, dev->name, dev);if (unlikely(ret < 0)) {netdev_err(priv->dev,"%s: ERROR: allocating the IRQ %d (error: %d)\n",__func__, dev->irq, ret);goto irq_error;}/* Request the Wake IRQ in case of another line is used for WoL */if (priv->wol_irq != dev->irq) {ret = request_irq(priv->wol_irq, stmmac_interrupt,IRQF_SHARED, dev->name, dev);if (unlikely(ret < 0)) {netdev_err(priv->dev,"%s: ERROR: allocating the WoL IRQ %d (%d)\n",__func__, priv->wol_irq, ret);goto wolirq_error;}}/* Request the IRQ lines */if (priv->lpi_irq > 0) {ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,dev->name, dev);if (unlikely(ret < 0)) {netdev_err(priv->dev,"%s: ERROR: allocating the LPI IRQ %d (%d)\n",__func__, priv->lpi_irq, ret);goto lpiirq_error;}}stmmac_enable_all_queues(priv);stmmac_start_all_queues(priv);return 0;
再看看对硬件操作比较多的stmmac_hw_setup(dev, true); 这个函数中主要初始化了DMA和MAC,并使能了DMA
static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)-> ret = stmmac_init_dma_engine(priv);-> stmmac_reset(priv, priv->ioaddr);-> stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg, atds);-> stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);-> stmmac_init_rx/tx_chan()-> stmmac_set_rx/tx_tail_ptr(priv, priv->ioaddr,rx_q->rx_tail_addr, chan) 把收发队列地址配置到网卡-> stmmac_core_init(priv, priv->hw, dev); //这是个回调函数 对应的是 dwmac1000_dma_init(),在probe时注册的-> stmmac_mac_set(priv, priv->ioaddr, true);-> stmmac_dma_operation_mode(priv);-> stmmac_set_rings_length(priv);-> stmmac_start_all_dma(priv);
对于DMA和MAC的初始化我整理成了流程图表
下面是对MAC的初始化流程