Logo

Linux 核心

6.16.0-rc4

快速搜尋

目錄

  • 開發流程
  • 提交補丁
  • 行為準則
  • 維護者手冊
  • 所有開發流程文件
  • 核心 API
  • 驅動 API
  • 子系統
    • 核心子系統
    • 人機介面
    • 網路介面
      • 網路
      • NetLabel
      • InfiniBand
      • ISDN
      • MHI
    • 儲存介面
    • 其他子系統
  • 鎖
  • 許可規則
  • 編寫文件
  • 開發工具
  • 測試指南
  • 駭客指南
  • 追蹤
  • 故障注入
  • 熱補丁
  • Rust
  • 管理
  • 構建系統
  • 報告問題
  • 使用者空間工具
  • 使用者空間 API
  • 韌體
  • 韌體和裝置樹
  • CPU 架構
  • 未分類的文件
  • 翻譯

本頁

  • 顯示原始碼

phylink¶

概述¶

phylink 是一種機制,用於支援直接連線到 MAC 的熱插拔網路模組,而無需在熱插拔事件時重新初始化介面卡。

phylink 目前支援傳統的基於 phylib 的設定、固定鏈路設定和 SFP(小型可插拔)模組。

操作模式¶

phylink 有幾種操作模式,具體取決於韌體設定。

  1. PHY 模式

    在 PHY 模式下,我們使用 phylib 從 PHY 讀取當前的鏈路設定,並將它們傳遞給 MAC 驅動程式。我們希望 MAC 驅動程式配置指定的模式,而不在鏈路上啟用任何協商。

  2. 固定模式

    就 MAC 驅動程式而言,固定模式與 PHY 模式相同。

  3. 帶內模式

    帶內模式與 802.3z、SGMII 和類似的介面模式一起使用,我們期望使用和遵守透過 serdes 通道傳送的帶內協商或控制字。

舉例來說,這意味著

&eth {
  phy = <&phy>;
  phy-mode = "sgmii";
};

不使用帶內 SGMII 信令。 PHY 應嚴格遵循其 mac_config() 函式中給定的設定。鏈路應在 mac_link_up() 和 mac_link_down() 函式中強制啟動或關閉。

&eth {
  managed = "in-band-status";
  phy = <&phy>;
  phy-mode = "sgmii";
};

使用帶內模式,其中來自 PHY 協商的結果透過 SGMII 控制字傳遞給 MAC,並且 MAC 應確認控制字。mac_link_up() 和 mac_link_down() 函式不得強制 MAC 側鏈路啟動和關閉。

將網路驅動程式轉換為 sfp/phylink 的粗略指南¶

本指南簡要介紹瞭如何將網路驅動程式從 phylib 轉換為 sfp/phylink 支援。 請傳送補丁來改進此文件。

  1. 可以選擇將網路驅動程式的 phylib 更新函式拆分為處理鏈路斷開和鏈路建立的兩個部分。 這可以作為單獨的準備提交來完成。

    可以在 git commit fc548b991fb0 中找到此準備工作的一個較舊示例,儘管它是拆分為三個部分;鏈路建立部分現在包括配置 MAC 以進行鏈路設定。 有關此內容的更多資訊,請參見 mac_link_up()。

  2. 替換

    select FIXED_PHY
    select PHYLIB
    

    用

    select PHYLINK
    

    在驅動程式的 Kconfig 節中。

  3. 新增

    #include <linux/phylink.h>
    

    到驅動程式的標頭檔案列表中。

  4. 新增

    struct phylink *phylink;
    struct phylink_config phylink_config;
    

    到驅動程式的私有資料結構。 我們將驅動程式的私有資料指標稱為 priv,驅動程式的私有資料結構稱為 struct foo_priv。

  5. 替換以下函式

    原始函式

    替換函式

    phy_start(phydev)

    phylink_start(priv->phylink)

    phy_stop(phydev)

    phylink_stop(priv->phylink)

    phy_mii_ioctl(phydev, ifr, cmd)

    phylink_mii_ioctl(priv->phylink, ifr, cmd)

    phy_ethtool_get_wol(phydev, wol)

    phylink_ethtool_get_wol(priv->phylink, wol)

    phy_ethtool_set_wol(phydev, wol)

    phylink_ethtool_set_wol(priv->phylink, wol)

    phy_disconnect(phydev)

    phylink_disconnect_phy(priv->phylink)

    請注意,其中一些函式必須在 rtnl 鎖下呼叫,否則會發出警告。 通常情況下是這樣,除非它們是從驅動程式的暫停/恢復路徑中呼叫的。

  6. 使用以下方法新增/替換 ksettings 獲取/設定方法

    static int foo_ethtool_set_link_ksettings(struct net_device *dev,
                                              const struct ethtool_link_ksettings *cmd)
    {
            struct foo_priv *priv = netdev_priv(dev);
    
            return phylink_ethtool_ksettings_set(priv->phylink, cmd);
    }
    
    static int foo_ethtool_get_link_ksettings(struct net_device *dev,
                                              struct ethtool_link_ksettings *cmd)
    {
            struct foo_priv *priv = netdev_priv(dev);
    
            return phylink_ethtool_ksettings_get(priv->phylink, cmd);
    }
    
  7. 替換對

    phy_dev = of_phy_connect(dev, node, link_func, flags, phy_interface);
    

    以及相關程式碼的呼叫,並將其替換為對

    err = phylink_of_phy_connect(priv->phylink, node, flags);
    

    在大多數情況下,flags 可以為零;如果在 DT 節點 node 中指定了 PHY,則這些標誌將傳遞給此函式呼叫中的 phy_attach_direct()。

    node 應該是包含網路 phy 屬性、固定鏈路屬性的 DT 節點,並且還將包含 sfp 屬性。

    還應刪除固定鏈路的設定; 這些由 phylink 在內部處理。

    of_phy_connect() 還傳遞了用於鏈路更新的函式指標。 此函式被 (8) 中描述的不同形式的 MAC 更新所取代。

    PHY 的 supported/advertised 的操作發生在 phylink 內部,基於驗證回撥,請參見下面的 (8)。

    請注意,驅動程式不再需要儲存 phy_interface,還要注意 phy_interface 變成了一個動態屬性,就像速度、雙工等設定一樣。

    最後,請注意 MAC 驅動程式不再能夠直接訪問 PHY; 這是因為在 phylink 模型中,PHY 可以是動態的。

  8. 向驅動程式新增一個 struct phylink_mac_ops 例項,它是一個函式指標表,並實現這些函式。 用於 of_phy_connect() 的舊鏈路更新函式變成了三個方法:mac_link_up()、mac_link_down() 和 mac_config()。 如果執行了步驟 1,則功能將被拆分到那裡。

    重要的是,如果使用了帶內協商,則 mac_link_up() 和 mac_link_down() 不會阻止帶內協商完成,因為這些函式是在帶內鏈路狀態更改時呼叫的 - 否則鏈路將永遠不會啟動。

    mac_get_caps() 方法是可選的,如果提供,則應返回為傳遞的 interface 模式支援的 phylink MAC 功能。 通常,無需實現此方法。 Phylink 將結合 interface 的允許功能使用這些功能來確定允許的 ethtool 鏈路模式。

    mac_link_state() 方法用於從 MAC 讀取鏈路狀態,並報告 MAC 當前使用的設定。 這對於帶內協商方法(例如 1000base-X 和 SGMII)尤其重要。

    mac_link_up() 方法用於通知 MAC 鏈路已啟動。 該呼叫僅包括協商模式和介面以供參考。 還提供了最終的鏈路引數(速度、雙工和流量控制/暫停啟用設定),當 MAC 和 PCS 沒有緊密整合的,或者當設定不是來自帶內協商時,應使用這些引數來配置 MAC。

    mac_config() 方法用於使用請求的狀態更新 MAC,並且在更改 MAC 配置時必須避免不必要地斷開鏈路。 這意味著該函式應修改狀態,並且僅在絕對需要更改 MAC 配置時才斷開鏈路。 可以在 drivers/net/ethernet/marvell/mvneta.c 中的 mvneta_mac_config() 中找到有關如何執行此操作的示例。

    有關這些方法的更多資訊,請參見 struct phylink_mac_ops 中的內聯文件。

  9. 使用對與您的 struct net_device 關聯的 struct device 的引用來填充 struct phylink_config 欄位

    priv->phylink_config.dev = &dev.dev;
    priv->phylink_config.type = PHYLINK_NETDEV;
    

    填充您的 MAC 可以處理的各種速度、暫停和雙工模式

    priv->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD;
    
  10. 某些乙太網控制器與 PCS(物理編碼子層)塊配對工作,該塊可以處理編碼/解碼、鏈路建立檢測和自動協商等。 雖然某些 MAC 具有內部 PCS,其操作是透明的,但其他一些 MAC 需要專用的 PCS 配置才能使鏈路正常工作。 在這種情況下,phylink 透過 struct phylink_pcs 提供 PCS 抽象。

    確定您的驅動程式是否有一個或多個內部 PCS 塊,以及您的控制器是否可以使用可能在內部連線到您的控制器的外部 PCS 塊。

    如果您的控制器沒有任何內部 PCS,則可以轉到步驟 11。

    如果您的乙太網控制器包含一個或多個 PCS 塊,請在驅動程式的私有資料結構中為每個 PCS 塊建立一個 struct phylink_pcs 例項

    struct phylink_pcs pcs;
    

    填充相關的 struct phylink_pcs_ops 以配置您的 PCS。 建立一個 pcs_get_state() 函式,該函式報告帶內鏈路狀態,一個 pcs_config() 函式,該函式根據 phylink 提供的引數配置您的 PCS,以及一個 pcs_validate() 函式,該函式向 phylink 報告您的 PCS 接受的所有配置引數

    struct phylink_pcs_ops foo_pcs_ops = {
            .pcs_validate = foo_pcs_validate,
            .pcs_get_state = foo_pcs_get_state,
            .pcs_config = foo_pcs_config,
    };
    

    安排將 PCS 鏈路狀態中斷轉發到 phylink 中,透過

    phylink_pcs_change(pcs, link_is_up);
    

    其中,如果鏈路當前已啟動,則 link_is_up 為 true,否則為 false。 如果 PCS 無法提供這些中斷,則應在建立 PCS 時設定 pcs->pcs_poll = true;。

  11. 如果您的控制器依賴於或接受透過其自身驅動程式控制的外部 PCS 的存在,請在您的驅動程式私有資料結構中新增一個指向 phylink_pcs 例項的指標

    struct phylink_pcs *pcs;
    

    獲取實際 PCS 例項的方式取決於平臺,一些 PCS 位於 MDIO 總線上,並透過傳遞指向相應的 struct mii_bus 的指標和該總線上 PCS 的地址來獲取。 在此示例中,我們假設控制器連線到 Lynx PCS 例項

    priv->pcs = lynx_pcs_create_mdiodev(bus, 0);
    

    可以基於韌體資訊恢復一些 PCS

    priv->pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node));
    
  12. 填充 mac_select_pcs() 回撥,並將其新增到您的 struct phylink_mac_ops ops 集中。 此函式必須返回一個指向將用於請求的鏈路配置的相關 struct phylink_pcs 的指標

    static struct phylink_pcs *foo_select_pcs(struct phylink_config *config,
                                              phy_interface_t interface)
    {
            struct foo_priv *priv = container_of(config, struct foo_priv,
                                                 phylink_config);
    
            if ( /* 'interface' needs a PCS to function */ )
                    return priv->pcs;
    
            return NULL;
    }
    

    有關具有多個內部 PCS 的驅動程式的示例,請參見 mvpp2_select_pcs()。

  13. 填充您的 MAC 可以輸出的所有 phy_interface_t(即,所有 MAC 到 PHY 鏈路模式)。 以下示例顯示了可以處理所有 RGMII 模式、SGMII 和 1000BaseX 的 MAC 的配置。 您必須根據您的 MAC 和與此 MAC 關聯的所有 PCS 的功能來調整這些設定,而不僅僅是您希望使用的介面

    phy_interface_set_rgmii(priv->phylink_config.supported_interfaces);
     __set_bit(PHY_INTERFACE_MODE_SGMII,
               priv->phylink_config.supported_interfaces);
     __set_bit(PHY_INTERFACE_MODE_1000BASEX,
               priv->phylink_config.supported_interfaces);
    
  14. 從探測函式中刪除對 PHY 的 of_parse_phandle() 的呼叫、對固定鏈路的 of_phy_register_fixed_link() 等,並將其替換為

    struct phylink *phylink;
    
    phylink = phylink_create(&priv->phylink_config, node, phy_mode, &phylink_ops);
    if (IS_ERR(phylink)) {
            err = PTR_ERR(phylink);
            fail probe;
    }
    
    priv->phylink = phylink;
    

    並透過呼叫來適當地安排在探測失敗路徑和移除路徑中銷燬 phylink

    phylink_destroy(priv->phylink);
    
  15. 安排將 MAC 鏈路狀態中斷轉發到 phylink 中,透過

    phylink_mac_change(priv->phylink, link_is_up);
    

    其中,如果鏈路當前已啟動,則 link_is_up 為 true,否則為 false。

  16. 驗證驅動程式是否不呼叫

    netif_carrier_on()
    netif_carrier_off()
    

    因為這些會干擾 phylink 對鏈路狀態的跟蹤,並導致 phylink 省略透過 mac_link_up() 和 mac_link_down() 方法的呼叫。

網路驅動程式應透過其暫停/恢復路徑呼叫 phylink_stop() 和 phylink_start(),這可確保根據需要呼叫適當的 struct phylink_mac_ops 方法。

有關在 DT 中描述 SFP 插槽的資訊,請參見核心原始碼樹 Documentation/devicetree/bindings/net/sff,sfp.yaml 中的繫結文件。

©核心開發社群。 | 由 Sphinx 5.3.0 & Alabaster 0.7.16 強力驅動 | 頁面原始碼