sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget*/translations/zh_CN/networking/sfp-phylinkmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/zh_TW/networking/sfp-phylinkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/it_IT/networking/sfp-phylinkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/ja_JP/networking/sfp-phylinkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/ko_KR/networking/sfp-phylinkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hPortuguese (Brazilian)}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/pt_BR/networking/sfp-phylinkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/sp_SP/networking/sfp-phylinkmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhhD/var/lib/git/docbuild/linux/Documentation/networking/sfp-phylink.rsthKubhsection)}(hhh](htitle)}(hphylinkh]hphylink}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hOverviewh]hOverview}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh paragraph)}(hphylink is a mechanism to support hot-pluggable networking modules directly connected to a MAC without needing to re-initialise the adapter on hot-plug events.h]hphylink is a mechanism to support hot-pluggable networking modules directly connected to a MAC without needing to re-initialise the adapter on hot-plug events.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(h}phylink supports conventional phylib-based setups, fixed link setups and SFP (Small Formfactor Pluggable) modules at present.h]h}phylink supports conventional phylib-based setups, fixed link setups and SFP (Small Formfactor Pluggable) modules at present.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubeh}(h]overviewah ]h"]overviewah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hModes of operationh]hModes of operation}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hNphylink has several modes of operation, which depend on the firmware settings.h]hNphylink has several modes of operation, which depend on the firmware settings.}(hj%hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubhenumerated_list)}(hhh](h list_item)}(hPHY mode In PHY mode, we use phylib to read the current link settings from the PHY, and pass them to the MAC driver. We expect the MAC driver to configure exactly the modes that are specified without any negotiation being enabled on the link. h](h)}(hPHY modeh]hPHY mode}(hj>hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj:ubh)}(hIn PHY mode, we use phylib to read the current link settings from the PHY, and pass them to the MAC driver. We expect the MAC driver to configure exactly the modes that are specified without any negotiation being enabled on the link.h]hIn PHY mode, we use phylib to read the current link settings from the PHY, and pass them to the MAC driver. We expect the MAC driver to configure exactly the modes that are specified without any negotiation being enabled on the link.}(hjLhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj:ubeh}(h]h ]h"]h$]h&]uh1j8hj5hhhhhNubj9)}(hVFixed mode Fixed mode is the same as PHY mode as far as the MAC driver is concerned. h](h)}(h Fixed modeh]h Fixed mode}(hjdhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj`ubh)}(hIFixed mode is the same as PHY mode as far as the MAC driver is concerned.h]hIFixed mode is the same as PHY mode as far as the MAC driver is concerned.}(hjrhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hj`ubeh}(h]h ]h"]h$]h&]uh1j8hj5hhhhhNubj9)}(hIn-band mode In-band mode is used with 802.3z, SGMII and similar interface modes, and we are expecting to use and honor the in-band negotiation or control word sent across the serdes channel. h](h)}(h In-band modeh]h In-band mode}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK#hjubh)}(hIn-band mode is used with 802.3z, SGMII and similar interface modes, and we are expecting to use and honor the in-band negotiation or control word sent across the serdes channel.h]hIn-band mode is used with 802.3z, SGMII and similar interface modes, and we are expecting to use and honor the in-band negotiation or control word sent across the serdes channel.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK%hjubeh}(h]h ]h"]h$]h&]uh1j8hj5hhhhhNubeh}(h]h ]h"]h$]h&]enumtypearabicprefixhsuffix.uh1j3hjhhhhhKubh)}(h$By example, what this means is that:h]h$By example, what this means is that:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK)hjhhubh literal_block)}(h/ð { phy = <&phy>; phy-mode = "sgmii"; };h]h/ð { phy = <&phy>; phy-mode = "sgmii"; };}hjsbah}(h]h ]h"]h$]h&]hhƌforcelanguagenonehighlight_args}uh1jhhhK+hjhhubh)}(hXdoes not use in-band SGMII signalling. The PHY is expected to follow exactly the settings given to it in its :c:func:`mac_config` function. The link should be forced up or down appropriately in the :c:func:`mac_link_up` and :c:func:`mac_link_down` functions.h](hndoes not use in-band SGMII signalling. The PHY is expected to follow exactly the settings given to it in its }(hjhhhNhNubh)}(h:c:func:`mac_config`h]hliteral)}(hjh]h mac_config()}(hjhhhNhNubah}(h]h ](xrefcc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocnetworking/sfp-phylink refdomainjreftypefunc refexplicitrefwarn reftarget mac_configuh1hhhhK2hjubhE function. The link should be forced up or down appropriately in the }(hjhhhNhNubh)}(h:c:func:`mac_link_up`h]j)}(hj h]h mac_link_up()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhK2hjubh and }(hjhhhNhNubh)}(h:c:func:`mac_link_down`h]j)}(hj0h]hmac_link_down()}(hj2hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj.ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_downuh1hhhhK2hjubh functions.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK2hjhhubj)}(hMð { managed = "in-band-status"; phy = <&phy>; phy-mode = "sgmii"; };h]hMð { managed = "in-band-status"; phy = <&phy>; phy-mode = "sgmii"; };}hjWsbah}(h]h ]h"]h$]h&]hhjjnonej}uh1jhhhK7hjhhubh)}(hXuses in-band mode, where results from the PHY's negotiation are passed to the MAC through the SGMII control word, and the MAC is expected to acknowledge the control word. The :c:func:`mac_link_up` and :c:func:`mac_link_down` functions must not force the MAC side link up and down.h](huses in-band mode, where results from the PHY’s negotiation are passed to the MAC through the SGMII control word, and the MAC is expected to acknowledge the control word. The }(hjghhhNhNubh)}(h:c:func:`mac_link_up`h]j)}(hjqh]h mac_link_up()}(hjshhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjoubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhK?hjgubh and }(hjghhhNhNubh)}(h:c:func:`mac_link_down`h]j)}(hjh]hmac_link_down()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_downuh1hhhhK?hjgubh8 functions must not force the MAC side link up and down.}(hjghhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK?hjhhubeh}(h]modes-of-operationah ]h"]modes of operationah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(h9Rough guide to converting a network driver to sfp/phylinkh]h9Rough guide to converting a network driver to sfp/phylink}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKFubh)}(hThis guide briefly describes how to convert a network driver from phylib to the sfp/phylink support. Please send patches to improve this documentation.h]hThis guide briefly describes how to convert a network driver from phylib to the sfp/phylink support. Please send patches to improve this documentation.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKHhjhhubj4)}(hhh](j9)}(hXOptionally split the network driver's phylib update function into two parts dealing with link-down and link-up. This can be done as a separate preparation commit. An older example of this preparation can be found in git commit fc548b991fb0, although this was splitting into three parts; the link-up part now includes configuring the MAC for the link settings. Please see :c:func:`mac_link_up` for more information on this. h](h)}(hOptionally split the network driver's phylib update function into two parts dealing with link-down and link-up. This can be done as a separate preparation commit.h]hOptionally split the network driver’s phylib update function into two parts dealing with link-down and link-up. This can be done as a separate preparation commit.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKLhjubh)}(hXAn older example of this preparation can be found in git commit fc548b991fb0, although this was splitting into three parts; the link-up part now includes configuring the MAC for the link settings. Please see :c:func:`mac_link_up` for more information on this.h](hAn older example of this preparation can be found in git commit fc548b991fb0, although this was splitting into three parts; the link-up part now includes configuring the MAC for the link settings. Please see }(hjhhhNhNubh)}(h:c:func:`mac_link_up`h]j)}(hjh]h mac_link_up()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhKPhjubh for more information on this.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKPhjubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hrReplace:: select FIXED_PHY select PHYLIB with:: select PHYLINK in the driver's Kconfig stanza. h](h)}(h Replace::h]hReplace:}(hj2hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKUhj.ubj)}(hselect FIXED_PHY select PHYLIBh]hselect FIXED_PHY select PHYLIB}hj@sbah}(h]h ]h"]h$]h&]hhuh1jhhhKWhj.ubh)}(hwith::h]hwith:}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKZhj.ubj)}(hselect PHYLINKh]hselect PHYLINK}hj\sbah}(h]h ]h"]h$]h&]hhuh1jhhhK\hj.ubh)}(hin the driver's Kconfig stanza.h]h!in the driver’s Kconfig stanza.}(hjjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK^hj.ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hNAdd:: #include to the driver's list of header files. h](h)}(hAdd::h]hAdd:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK`hj~ubj)}(h#include h]h#include }hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKbhj~ubh)}(h%to the driver's list of header files.h]h'to the driver’s list of header files.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKdhj~ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hXAdd:: struct phylink *phylink; struct phylink_config phylink_config; to the driver's private data structure. We shall refer to the driver's private data pointer as ``priv`` below, and the driver's private data structure as ``struct foo_priv``. h](h)}(hAdd::h]hAdd:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKfhjubj)}(h>struct phylink *phylink; struct phylink_config phylink_config;h]h>struct phylink *phylink; struct phylink_config phylink_config;}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhhjubh)}(hto the driver's private data structure. We shall refer to the driver's private data pointer as ``priv`` below, and the driver's private data structure as ``struct foo_priv``.h](hdto the driver’s private data structure. We shall refer to the driver’s private data pointer as }(hjhhhNhNubj)}(h``priv``h]hpriv}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh5 below, and the driver’s private data structure as }(hjhhhNhNubj)}(h``struct foo_priv``h]hstruct foo_priv}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKkhjubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hXReplace the following functions: .. flat-table:: :header-rows: 1 :widths: 1 1 :stub-columns: 0 * - Original function - Replacement function * - 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) Please note that some of these functions must be called under the rtnl lock, and will warn if not. This will normally be the case, except if these are called from the driver suspend/resume paths. h](h)}(h Replace the following functions:h]h Replace the following functions:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKohj ubhtable)}(hhh]htgroup)}(hhh](hcolspec)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j&hj#ubj')}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j&hj#ubhthead)}(hhh]hrow)}(hhh](hentry)}(hhh]h)}(hOriginal functionh]hOriginal function}(hjKhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKvhjHubah}(h]h ]h"]h$]h&]uh1jFhjCubjG)}(hhh]h)}(hReplacement functionh]hReplacement function}(hjbhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKwhj_ubah}(h]h ]h"]h$]h&]uh1jFhjCubeh}(h]h ]h"]h$]h&]uh1jAhj>ubah}(h]h ]h"]h$]h&]uh1j<hj#ubhtbody)}(hhh](jB)}(hhh](jG)}(hhh]h)}(hphy_start(phydev)h]hphy_start(phydev)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKxhjubah}(h]h ]h"]h$]h&]uh1jFhjubjG)}(hhh]h)}(hphylink_start(priv->phylink)h]hphylink_start(priv->phylink)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKyhjubah}(h]h ]h"]h$]h&]uh1jFhjubeh}(h]h ]h"]h$]h&]uh1jAhjubjB)}(hhh](jG)}(hhh]h)}(hphy_stop(phydev)h]hphy_stop(phydev)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKzhjubah}(h]h ]h"]h$]h&]uh1jFhjubjG)}(hhh]h)}(hphylink_stop(priv->phylink)h]hphylink_stop(priv->phylink)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK{hjubah}(h]h ]h"]h$]h&]uh1jFhjubeh}(h]h ]h"]h$]h&]uh1jAhjubjB)}(hhh](jG)}(hhh]h)}(hphy_mii_ioctl(phydev, ifr, cmd)h]hphy_mii_ioctl(phydev, ifr, cmd)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK|hjubah}(h]h ]h"]h$]h&]uh1jFhjubjG)}(hhh]h)}(h*phylink_mii_ioctl(priv->phylink, ifr, cmd)h]h*phylink_mii_ioctl(priv->phylink, ifr, cmd)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK}hjubah}(h]h ]h"]h$]h&]uh1jFhjubeh}(h]h ]h"]h$]h&]uh1jAhjubjB)}(hhh](jG)}(hhh]h)}(h phy_ethtool_get_wol(phydev, wol)h]h phy_ethtool_get_wol(phydev, wol)}(hj2hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK~hj/ubah}(h]h ]h"]h$]h&]uh1jFhj,ubjG)}(hhh]h)}(h+phylink_ethtool_get_wol(priv->phylink, wol)h]h+phylink_ethtool_get_wol(priv->phylink, wol)}(hjIhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjFubah}(h]h ]h"]h$]h&]uh1jFhj,ubeh}(h]h ]h"]h$]h&]uh1jAhjubjB)}(hhh](jG)}(hhh]h)}(h phy_ethtool_set_wol(phydev, wol)h]h phy_ethtool_set_wol(phydev, wol)}(hjihhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjfubah}(h]h ]h"]h$]h&]uh1jFhjcubjG)}(hhh]h)}(h+phylink_ethtool_set_wol(priv->phylink, wol)h]h+phylink_ethtool_set_wol(priv->phylink, wol)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj}ubah}(h]h ]h"]h$]h&]uh1jFhjcubeh}(h]h ]h"]h$]h&]uh1jAhjubjB)}(hhh](jG)}(hhh]h)}(hphy_disconnect(phydev)h]hphy_disconnect(phydev)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jFhjubjG)}(hhh]h)}(h%phylink_disconnect_phy(priv->phylink)h]h%phylink_disconnect_phy(priv->phylink)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jFhjubeh}(h]h ]h"]h$]h&]uh1jAhjubeh}(h]h ]h"]h$]h&]uh1jhj#ubeh}(h]h ]h"]h$]h&]colsKuh1j!hjubah}(h]h ]h"]h$]h&]uh1jhj ubh)}(hPlease note that some of these functions must be called under the rtnl lock, and will warn if not. This will normally be the case, except if these are called from the driver suspend/resume paths.h]hPlease note that some of these functions must be called under the rtnl lock, and will warn if not. This will normally be the case, except if these are called from the driver suspend/resume paths.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hXAdd/replace ksettings get/set methods with: .. code-block:: c 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); } h](h)}(h+Add/replace ksettings get/set methods with:h]h+Add/replace ksettings get/set methods with:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hXstatic 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); }h]hXstatic 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); }}hj sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhKhjubeh}(h]h ]h"]h$]h&]uh1j8hjhhhNhNubj9)}(hXReplace the call to:: phy_dev = of_phy_connect(dev, node, link_func, flags, phy_interface); and associated code with a call to:: err = phylink_of_phy_connect(priv->phylink, node, flags); For the most part, ``flags`` can be zero; these flags are passed to the phy_attach_direct() inside this function call if a PHY is specified in the DT node ``node``. ``node`` should be the DT node which contains the network phy property, fixed link properties, and will also contain the sfp property. The setup of fixed links should also be removed; these are handled internally by phylink. of_phy_connect() was also passed a function pointer for link updates. This function is replaced by a different form of MAC updates described below in (8). Manipulation of the PHY's supported/advertised happens within phylink based on the validate callback, see below in (8). Note that the driver no longer needs to store the ``phy_interface``, and also note that ``phy_interface`` becomes a dynamic property, just like the speed, duplex etc. settings. Finally, note that the MAC driver has no direct access to the PHY anymore; that is because in the phylink model, the PHY can be dynamic. h](h)}(hReplace the call to::h]hReplace the call to:}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hEphy_dev = of_phy_connect(dev, node, link_func, flags, phy_interface);h]hEphy_dev = of_phy_connect(dev, node, link_func, flags, phy_interface);}hj1sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjubh)}(h$and associated code with a call to::h]h#and associated code with a call to:}(hj?hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(h9err = phylink_of_phy_connect(priv->phylink, node, flags);h]h9err = phylink_of_phy_connect(priv->phylink, node, flags);}hjMsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjubh)}(hFor the most part, ``flags`` can be zero; these flags are passed to the phy_attach_direct() inside this function call if a PHY is specified in the DT node ``node``.h](hFor the most part, }(hj[hhhNhNubj)}(h ``flags``h]hflags}(hjchhhNhNubah}(h]h ]h"]h$]h&]uh1jhj[ubh can be zero; these flags are passed to the phy_attach_direct() inside this function call if a PHY is specified in the DT node }(hj[hhhNhNubj)}(h``node``h]hnode}(hjuhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj[ubh.}(hj[hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(h``node`` should be the DT node which contains the network phy property, fixed link properties, and will also contain the sfp property.h](j)}(h``node``h]hnode}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh~ should be the DT node which contains the network phy property, fixed link properties, and will also contain the sfp property.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hYThe setup of fixed links should also be removed; these are handled internally by phylink.h]hYThe setup of fixed links should also be removed; these are handled internally by phylink.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hof_phy_connect() was also passed a function pointer for link updates. This function is replaced by a different form of MAC updates described below in (8).h]hof_phy_connect() was also passed a function pointer for link updates. This function is replaced by a different form of MAC updates described below in (8).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hwManipulation of the PHY's supported/advertised happens within phylink based on the validate callback, see below in (8).h]hyManipulation of the PHY’s supported/advertised happens within phylink based on the validate callback, see below in (8).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hNote that the driver no longer needs to store the ``phy_interface``, and also note that ``phy_interface`` becomes a dynamic property, just like the speed, duplex etc. settings.h](h2Note that the driver no longer needs to store the }(hjhhhNhNubj)}(h``phy_interface``h]h phy_interface}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh, and also note that }(hjhhhNhNubj)}(h``phy_interface``h]h phy_interface}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhG becomes a dynamic property, just like the speed, duplex etc. settings.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hFinally, note that the MAC driver has no direct access to the PHY anymore; that is because in the phylink model, the PHY can be dynamic.h]hFinally, note that the MAC driver has no direct access to the PHY anymore; that is because in the phylink model, the PHY can be dynamic.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hXAdd a :c:type:`struct phylink_mac_ops ` instance to the driver, which is a table of function pointers, and implement these functions. The old link update function for :c:func:`of_phy_connect` becomes three methods: :c:func:`mac_link_up`, :c:func:`mac_link_down`, and :c:func:`mac_config`. If step 1 was performed, then the functionality will have been split there. It is important that if in-band negotiation is used, :c:func:`mac_link_up` and :c:func:`mac_link_down` do not prevent the in-band negotiation from completing, since these functions are called when the in-band link state changes - otherwise the link will never come up. The :c:func:`mac_get_caps` method is optional, and if provided should return the phylink MAC capabilities that are supported for the passed ``interface`` mode. In general, there is no need to implement this method. Phylink will use these capabilities in combination with permissible capabilities for ``interface`` to determine the allowable ethtool link modes. The :c:func:`mac_link_state` method is used to read the link state from the MAC, and report back the settings that the MAC is currently using. This is particularly important for in-band negotiation methods such as 1000base-X and SGMII. The :c:func:`mac_link_up` method is used to inform the MAC that the link has come up. The call includes the negotiation mode and interface for reference only. The finalised link parameters are also supplied (speed, duplex and flow control/pause enablement settings) which should be used to configure the MAC when the MAC and PCS are not tightly integrated, or when the settings are not coming from in-band negotiation. The :c:func:`mac_config` method is used to update the MAC with the requested state, and must avoid unnecessarily taking the link down when making changes to the MAC configuration. This means the function should modify the state and only take the link down when absolutely necessary to change the MAC configuration. An example of how to do this can be found in :c:func:`mvneta_mac_config` in ``drivers/net/ethernet/marvell/mvneta.c``. For further information on these methods, please see the inline documentation in :c:type:`struct phylink_mac_ops `. h](h)}(hX}Add a :c:type:`struct phylink_mac_ops ` instance to the driver, which is a table of function pointers, and implement these functions. The old link update function for :c:func:`of_phy_connect` becomes three methods: :c:func:`mac_link_up`, :c:func:`mac_link_down`, and :c:func:`mac_config`. If step 1 was performed, then the functionality will have been split there.h](hAdd a }(hjhhhNhNubh)}(h2:c:type:`struct phylink_mac_ops `h]j)}(hj'h]hstruct phylink_mac_ops}(hj)hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj%ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_mac_opsuh1hhhhKhjubh instance to the driver, which is a table of function pointers, and implement these functions. The old link update function for }(hjhhhNhNubh)}(h:c:func:`of_phy_connect`h]j)}(hjJh]hof_phy_connect()}(hjLhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjHubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnjof_phy_connectuh1hhhhKhjubh becomes three methods: }(hjhhhNhNubh)}(h:c:func:`mac_link_up`h]j)}(hjmh]h mac_link_up()}(hjohhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjkubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhKhjubh, }(hjhhhNhNubh)}(h:c:func:`mac_link_down`h]j)}(hjh]hmac_link_down()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_downuh1hhhhKhjubh, and }(hjhhhNhNubh)}(h:c:func:`mac_config`h]j)}(hjh]h mac_config()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_configuh1hhhhKhjubhM. If step 1 was performed, then the functionality will have been split there.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hX It is important that if in-band negotiation is used, :c:func:`mac_link_up` and :c:func:`mac_link_down` do not prevent the in-band negotiation from completing, since these functions are called when the in-band link state changes - otherwise the link will never come up.h](h5It is important that if in-band negotiation is used, }(hjhhhNhNubh)}(h:c:func:`mac_link_up`h]j)}(hjh]h mac_link_up()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhKhjubh and }(hjhhhNhNubh)}(h:c:func:`mac_link_down`h]j)}(hjh]hmac_link_down()}(hj hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_downuh1hhhhKhjubh do not prevent the in-band negotiation from completing, since these functions are called when the in-band link state changes - otherwise the link will never come up.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hXhThe :c:func:`mac_get_caps` method is optional, and if provided should return the phylink MAC capabilities that are supported for the passed ``interface`` mode. In general, there is no need to implement this method. Phylink will use these capabilities in combination with permissible capabilities for ``interface`` to determine the allowable ethtool link modes.h](hThe }(hj.hhhNhNubh)}(h:c:func:`mac_get_caps`h]j)}(hj8h]hmac_get_caps()}(hj:hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj6ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_get_capsuh1hhhhKhj.ubhr method is optional, and if provided should return the phylink MAC capabilities that are supported for the passed }(hj.hhhNhNubj)}(h ``interface``h]h interface}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj.ubh mode. In general, there is no need to implement this method. Phylink will use these capabilities in combination with permissible capabilities for }(hj.hhhNhNubj)}(h ``interface``h]h interface}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj.ubh/ to determine the allowable ethtool link modes.}(hj.hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hThe :c:func:`mac_link_state` method is used to read the link state from the MAC, and report back the settings that the MAC is currently using. This is particularly important for in-band negotiation methods such as 1000base-X and SGMII.h](hThe }(hjhhhNhNubh)}(h:c:func:`mac_link_state`h]j)}(hjh]hmac_link_state()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnjmac_link_stateuh1hhhhKhjubh method is used to read the link state from the MAC, and report back the settings that the MAC is currently using. This is particularly important for in-band negotiation methods such as 1000base-X and SGMII.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hXThe :c:func:`mac_link_up` method is used to inform the MAC that the link has come up. The call includes the negotiation mode and interface for reference only. The finalised link parameters are also supplied (speed, duplex and flow control/pause enablement settings) which should be used to configure the MAC when the MAC and PCS are not tightly integrated, or when the settings are not coming from in-band negotiation.h](hThe }(hjhhhNhNubh)}(h:c:func:`mac_link_up`h]j)}(hjh]h mac_link_up()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhKhjubhX method is used to inform the MAC that the link has come up. The call includes the negotiation mode and interface for reference only. The finalised link parameters are also supplied (speed, duplex and flow control/pause enablement settings) which should be used to configure the MAC when the MAC and PCS are not tightly integrated, or when the settings are not coming from in-band negotiation.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hXThe :c:func:`mac_config` method is used to update the MAC with the requested state, and must avoid unnecessarily taking the link down when making changes to the MAC configuration. This means the function should modify the state and only take the link down when absolutely necessary to change the MAC configuration. An example of how to do this can be found in :c:func:`mvneta_mac_config` in ``drivers/net/ethernet/marvell/mvneta.c``.h](hThe }(hjhhhNhNubh)}(h:c:func:`mac_config`h]j)}(hjh]h mac_config()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_configuh1hhhhKhjubhXR method is used to update the MAC with the requested state, and must avoid unnecessarily taking the link down when making changes to the MAC configuration. This means the function should modify the state and only take the link down when absolutely necessary to change the MAC configuration. An example of how to do this can be found in }(hjhhhNhNubh)}(h:c:func:`mvneta_mac_config`h]j)}(hj h]hmvneta_mac_config()}(hj hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnjmvneta_mac_configuh1hhhhKhjubh in }(hjhhhNhNubj)}(h)``drivers/net/ethernet/marvell/mvneta.c``h]h%drivers/net/ethernet/marvell/mvneta.c}(hj3 hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hFor further information on these methods, please see the inline documentation in :c:type:`struct phylink_mac_ops `.h](hQFor further information on these methods, please see the inline documentation in }(hjK hhhNhNubh)}(h2:c:type:`struct phylink_mac_ops `h]j)}(hjU h]hstruct phylink_mac_ops}(hjW hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhjS ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_mac_opsuh1hhhhKhjK ubh.}(hjK hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hXFill-in the :c:type:`struct phylink_config ` fields with a reference to the :c:type:`struct device ` associated to your :c:type:`struct net_device `: .. code-block:: c priv->phylink_config.dev = &dev.dev; priv->phylink_config.type = PHYLINK_NETDEV; Fill-in the various speeds, pause and duplex modes your MAC can handle: .. code-block:: c priv->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD; h](h)}(hFill-in the :c:type:`struct phylink_config ` fields with a reference to the :c:type:`struct device ` associated to your :c:type:`struct net_device `:h](h Fill-in the }(hj hhhNhNubh)}(h0:c:type:`struct phylink_config `h]j)}(hj h]hstruct phylink_config}(hj hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_configuh1hhhhKhj ubh fields with a reference to the }(hj hhhNhNubh)}(h :c:type:`struct device `h]j)}(hj h]h struct device}(hj hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjdeviceuh1hhhhKhj ubh associated to your }(hj hhhNhNubh)}(h(:c:type:`struct net_device `h]j)}(hj h]hstruct net_device}(hj hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnj net_deviceuh1hhhhKhj ubh:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubj)}(hPpriv->phylink_config.dev = &dev.dev; priv->phylink_config.type = PHYLINK_NETDEV;h]hPpriv->phylink_config.dev = &dev.dev; priv->phylink_config.type = PHYLINK_NETDEV;}hj sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhKhj ubh)}(hGFill-in the various speeds, pause and duplex modes your MAC can handle:h]hGFill-in the various speeds, pause and duplex modes your MAC can handle:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubj)}(hVpriv->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD;h]hVpriv->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD;}hj sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhKhj ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhNhNubj9)}(hX2Some Ethernet controllers work in pair with a PCS (Physical Coding Sublayer) block, that can handle among other things the encoding/decoding, link establishment detection and autonegotiation. While some MACs have internal PCS whose operation is transparent, some other require dedicated PCS configuration for the link to become functional. In that case, phylink provides a PCS abstraction through :c:type:`struct phylink_pcs `. Identify if your driver has one or more internal PCS blocks, and/or if your controller can use an external PCS block that might be internally connected to your controller. If your controller doesn't have any internal PCS, you can go to step 11. If your Ethernet controller contains one or several PCS blocks, create one :c:type:`struct phylink_pcs ` instance per PCS block within your driver's private data structure: .. code-block:: c struct phylink_pcs pcs; Populate the relevant :c:type:`struct phylink_pcs_ops ` to configure your PCS. Create a :c:func:`pcs_get_state` function that reports the inband link state, a :c:func:`pcs_config` function to configure your PCS according to phylink-provided parameters, and a :c:func:`pcs_validate` function that report to phylink all accepted configuration parameters for your PCS: .. code-block:: c struct phylink_pcs_ops foo_pcs_ops = { .pcs_validate = foo_pcs_validate, .pcs_get_state = foo_pcs_get_state, .pcs_config = foo_pcs_config, }; Arrange for PCS link state interrupts to be forwarded into phylink, via: .. code-block:: c phylink_pcs_change(pcs, link_is_up); where ``link_is_up`` is true if the link is currently up or false otherwise. If a PCS is unable to provide these interrupts, then it should set ``pcs->pcs_poll = true;`` when creating the PCS. h](h)}(hXSome Ethernet controllers work in pair with a PCS (Physical Coding Sublayer) block, that can handle among other things the encoding/decoding, link establishment detection and autonegotiation. While some MACs have internal PCS whose operation is transparent, some other require dedicated PCS configuration for the link to become functional. In that case, phylink provides a PCS abstraction through :c:type:`struct phylink_pcs `.h](hXSome Ethernet controllers work in pair with a PCS (Physical Coding Sublayer) block, that can handle among other things the encoding/decoding, link establishment detection and autonegotiation. While some MACs have internal PCS whose operation is transparent, some other require dedicated PCS configuration for the link to become functional. In that case, phylink provides a PCS abstraction through }(hj3 hhhNhNubh)}(h*:c:type:`struct phylink_pcs `h]j)}(hj= h]hstruct phylink_pcs}(hj? hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj; ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnj phylink_pcsuh1hhhhKhj3 ubh.}(hj3 hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj/ ubh)}(hIdentify if your driver has one or more internal PCS blocks, and/or if your controller can use an external PCS block that might be internally connected to your controller.h]hIdentify if your driver has one or more internal PCS blocks, and/or if your controller can use an external PCS block that might be internally connected to your controller.}(hjd hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj/ ubh)}(hHIf your controller doesn't have any internal PCS, you can go to step 11.h]hJIf your controller doesn’t have any internal PCS, you can go to step 11.}(hjr hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj/ ubh)}(hIf your Ethernet controller contains one or several PCS blocks, create one :c:type:`struct phylink_pcs ` instance per PCS block within your driver's private data structure:h](hKIf your Ethernet controller contains one or several PCS blocks, create one }(hj hhhNhNubh)}(h*:c:type:`struct phylink_pcs `h]j)}(hj h]hstruct phylink_pcs}(hj hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnj phylink_pcsuh1hhhhMhj ubhF instance per PCS block within your driver’s private data structure:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj/ ubj)}(hstruct phylink_pcs pcs;h]hstruct phylink_pcs pcs;}hj sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhM hj/ ubh)}(hX~Populate the relevant :c:type:`struct phylink_pcs_ops ` to configure your PCS. Create a :c:func:`pcs_get_state` function that reports the inband link state, a :c:func:`pcs_config` function to configure your PCS according to phylink-provided parameters, and a :c:func:`pcs_validate` function that report to phylink all accepted configuration parameters for your PCS:h](hPopulate the relevant }(hj hhhNhNubh)}(h2:c:type:`struct phylink_pcs_ops `h]j)}(hj h]hstruct phylink_pcs_ops}(hj hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_pcs_opsuh1hhhhMhj ubh! to configure your PCS. Create a }(hj hhhNhNubh)}(h:c:func:`pcs_get_state`h]j)}(hj h]hpcs_get_state()}(hj hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj pcs_get_stateuh1hhhhMhj ubh0 function that reports the inband link state, a }(hj hhhNhNubh)}(h:c:func:`pcs_config`h]j)}(hj h]h pcs_config()}(hj hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj pcs_configuh1hhhhMhj ubhP function to configure your PCS according to phylink-provided parameters, and a }(hj hhhNhNubh)}(h:c:func:`pcs_validate`h]j)}(hj3 h]hpcs_validate()}(hj5 hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj1 ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj pcs_validateuh1hhhhMhj ubhT function that report to phylink all accepted configuration parameters for your PCS:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj/ ubj)}(hstruct phylink_pcs_ops foo_pcs_ops = { .pcs_validate = foo_pcs_validate, .pcs_get_state = foo_pcs_get_state, .pcs_config = foo_pcs_config, };h]hstruct phylink_pcs_ops foo_pcs_ops = { .pcs_validate = foo_pcs_validate, .pcs_get_state = foo_pcs_get_state, .pcs_config = foo_pcs_config, };}hjZ sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhMhj/ ubh)}(hHArrange for PCS link state interrupts to be forwarded into phylink, via:h]hHArrange for PCS link state interrupts to be forwarded into phylink, via:}(hji hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj/ ubj)}(h$phylink_pcs_change(pcs, link_is_up);h]h$phylink_pcs_change(pcs, link_is_up);}hjw sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhM hj/ ubh)}(hwhere ``link_is_up`` is true if the link is currently up or false otherwise. If a PCS is unable to provide these interrupts, then it should set ``pcs->pcs_poll = true;`` when creating the PCS.h](hwhere }(hj hhhNhNubj)}(h``link_is_up``h]h link_is_up}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh| is true if the link is currently up or false otherwise. If a PCS is unable to provide these interrupts, then it should set }(hj hhhNhNubj)}(h``pcs->pcs_poll = true;``h]hpcs->pcs_poll = true;}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh when creating the PCS.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM$hj/ ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hXIf your controller relies on, or accepts the presence of an external PCS controlled through its own driver, add a pointer to a phylink_pcs instance in your driver private data structure: .. code-block:: c struct phylink_pcs *pcs; The way of getting an instance of the actual PCS depends on the platform, some PCS sit on an MDIO bus and are grabbed by passing a pointer to the corresponding :c:type:`struct mii_bus ` and the PCS's address on that bus. In this example, we assume the controller attaches to a Lynx PCS instance: .. code-block:: c priv->pcs = lynx_pcs_create_mdiodev(bus, 0); Some PCS can be recovered based on firmware information: .. code-block:: c priv->pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node)); h](h)}(hIf your controller relies on, or accepts the presence of an external PCS controlled through its own driver, add a pointer to a phylink_pcs instance in your driver private data structure:h]hIf your controller relies on, or accepts the presence of an external PCS controlled through its own driver, add a pointer to a phylink_pcs instance in your driver private data structure:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM(hj ubj)}(hstruct phylink_pcs *pcs;h]hstruct phylink_pcs *pcs;}hj sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhM,hj ubh)}(hX0The way of getting an instance of the actual PCS depends on the platform, some PCS sit on an MDIO bus and are grabbed by passing a pointer to the corresponding :c:type:`struct mii_bus ` and the PCS's address on that bus. In this example, we assume the controller attaches to a Lynx PCS instance:h](hThe way of getting an instance of the actual PCS depends on the platform, some PCS sit on an MDIO bus and are grabbed by passing a pointer to the corresponding }(hj hhhNhNubh)}(h":c:type:`struct mii_bus `h]j)}(hj h]hstruct mii_bus}(hj hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjmii_busuh1hhhhM0hj ubhp and the PCS’s address on that bus. In this example, we assume the controller attaches to a Lynx PCS instance:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM0hj ubj)}(h,priv->pcs = lynx_pcs_create_mdiodev(bus, 0);h]h,priv->pcs = lynx_pcs_create_mdiodev(bus, 0);}hj sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhM6hj ubh)}(h8Some PCS can be recovered based on firmware information:h]h8Some PCS can be recovered based on firmware information:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM:hj ubj)}(h;priv->pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node));h]h;priv->pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node));}hj- sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhM<hj ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhNhNubj9)}(hX3Populate the :c:func:`mac_select_pcs` callback and add it to your :c:type:`struct phylink_mac_ops ` set of ops. This function must return a pointer to the relevant :c:type:`struct phylink_pcs ` that will be used for the requested link configuration: .. code-block:: c 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; } See :c:func:`mvpp2_select_pcs` for an example of a driver that has multiple internal PCS. h](h)}(hXPopulate the :c:func:`mac_select_pcs` callback and add it to your :c:type:`struct phylink_mac_ops ` set of ops. This function must return a pointer to the relevant :c:type:`struct phylink_pcs ` that will be used for the requested link configuration:h](h Populate the }(hjF hhhNhNubh)}(h:c:func:`mac_select_pcs`h]j)}(hjP h]hmac_select_pcs()}(hjR hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjN ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnjmac_select_pcsuh1hhhhM@hjF ubh callback and add it to your }(hjF hhhNhNubh)}(h2:c:type:`struct phylink_mac_ops `h]j)}(hjs h]hstruct phylink_mac_ops}(hju hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhjq ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_mac_opsuh1hhhhM@hjF ubhA set of ops. This function must return a pointer to the relevant }(hjF hhhNhNubh)}(h*:c:type:`struct phylink_pcs `h]j)}(hj h]hstruct phylink_pcs}(hj hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnj phylink_pcsuh1hhhhM@hjF ubh8 that will be used for the requested link configuration:}(hjF hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM@hjB ubj)}(hXstatic 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; }h]hXstatic 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; }}hj sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhMEhjB ubh)}(hYSee :c:func:`mvpp2_select_pcs` for an example of a driver that has multiple internal PCS.h](hSee }(hj hhhNhNubh)}(h:c:func:`mvpp2_select_pcs`h]j)}(hj h]hmvpp2_select_pcs()}(hj hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnjmvpp2_select_pcsuh1hhhhMShj ubh; for an example of a driver that has multiple internal PCS.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMShjB ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hXFill-in all the :c:type:`phy_interface_t ` (i.e. all MAC to PHY link modes) that your MAC can output. The following example shows a configuration for a MAC that can handle all RGMII modes, SGMII and 1000BaseX. You must adjust these according to what your MAC and all PCS associated with this MAC are capable of, and not just the interface you wish to use: .. code-block:: c 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); h](h)}(hXtFill-in all the :c:type:`phy_interface_t ` (i.e. all MAC to PHY link modes) that your MAC can output. The following example shows a configuration for a MAC that can handle all RGMII modes, SGMII and 1000BaseX. You must adjust these according to what your MAC and all PCS associated with this MAC are capable of, and not just the interface you wish to use:h](hFill-in all the }(hj hhhNhNubh)}(h+:c:type:`phy_interface_t `h]j)}(hj h]hphy_interface_t}(hj hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphy_interface_tuh1hhhhMVhj ubhX9 (i.e. all MAC to PHY link modes) that your MAC can output. The following example shows a configuration for a MAC that can handle all RGMII modes, SGMII and 1000BaseX. You must adjust these according to what your MAC and all PCS associated with this MAC are capable of, and not just the interface you wish to use:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMVhj ubj)}(hphy_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);h]hphy_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);}hj8 sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhM\hj ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhNhNubj9)}(hX7Remove calls to of_parse_phandle() for the PHY, of_phy_register_fixed_link() for fixed links etc. from the probe function, and replace with: .. code-block:: c 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; and arrange to destroy the phylink in the probe failure path as appropriate and the removal path too by calling: .. code-block:: c phylink_destroy(priv->phylink); h](h)}(hRemove calls to of_parse_phandle() for the PHY, of_phy_register_fixed_link() for fixed links etc. from the probe function, and replace with:h]hRemove calls to of_parse_phandle() for the PHY, of_phy_register_fixed_link() for fixed links etc. from the probe function, and replace with:}(hjQ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMdhjM ubj)}(hstruct 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;h]hstruct 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;}hj_ sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhMhhjM ubh)}(hpand arrange to destroy the phylink in the probe failure path as appropriate and the removal path too by calling:h]hpand arrange to destroy the phylink in the probe failure path as appropriate and the removal path too by calling:}(hjn hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMthjM ubj)}(hphylink_destroy(priv->phylink);h]hphylink_destroy(priv->phylink);}hj| sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhMwhjM ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhNhNubj9)}(hArrange for MAC link state interrupts to be forwarded into phylink, via: .. code-block:: c phylink_mac_change(priv->phylink, link_is_up); where ``link_is_up`` is true if the link is currently up or false otherwise. h](h)}(hHArrange for MAC link state interrupts to be forwarded into phylink, via:h]hHArrange for MAC link state interrupts to be forwarded into phylink, via:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM{hj ubj)}(h.phylink_mac_change(priv->phylink, link_is_up);h]h.phylink_mac_change(priv->phylink, link_is_up);}hj sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhM~hj ubh)}(hLwhere ``link_is_up`` is true if the link is currently up or false otherwise.h](hwhere }(hj hhhNhNubj)}(h``link_is_up``h]h link_is_up}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh8 is true if the link is currently up or false otherwise.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubj9)}(hVerify that the driver does not call:: netif_carrier_on() netif_carrier_off() as these will interfere with phylink's tracking of the link state, and cause phylink to omit calls via the :c:func:`mac_link_up` and :c:func:`mac_link_down` methods. h](h)}(h&Verify that the driver does not call::h]h%Verify that the driver does not call:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubj)}(h&netif_carrier_on() netif_carrier_off()h]h&netif_carrier_on() netif_carrier_off()}hj sbah}(h]h ]h"]h$]h&]hhuh1jhhhMhj ubh)}(has these will interfere with phylink's tracking of the link state, and cause phylink to omit calls via the :c:func:`mac_link_up` and :c:func:`mac_link_down` methods.h](hmas these will interfere with phylink’s tracking of the link state, and cause phylink to omit calls via the }(hj hhhNhNubh)}(h:c:func:`mac_link_up`h]j)}(hjh]h mac_link_up()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]qh ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhMhj ubh and }(hj hhhNhNubh)}(h:c:func:`mac_link_down`h]j)}(hj%h]hmac_link_down()}(hj'hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj#ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_downuh1hhhhMhj ubh methods.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubeh}(h]h ]h"]h$]h&]uh1j8hjhhhhhNubeh}(h]h ]h"]h$]h&]jjjhjjuh1j3hjhhhhhKLubh)}(hNetwork drivers should call phylink_stop() and phylink_start() via their suspend/resume paths, which ensures that the appropriate :c:type:`struct phylink_mac_ops ` methods are called as necessary.h](hNetwork drivers should call phylink_stop() and phylink_start() via their suspend/resume paths, which ensures that the appropriate }(hjXhhhNhNubh)}(h2:c:type:`struct phylink_mac_ops `h]j)}(hjbh]hstruct phylink_mac_ops}(hjdhhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj`ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_mac_opsuh1hhhhMhjXubh! methods are called as necessary.}(hjXhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hFor information describing the SFP cage in DT, please see the binding documentation in the kernel source tree ``Documentation/devicetree/bindings/net/sff,sfp.yaml``.h](hnFor information describing the SFP cage in DT, please see the binding documentation in the kernel source tree }(hjhhhNhNubj)}(h6``Documentation/devicetree/bindings/net/sff,sfp.yaml``h]h2Documentation/devicetree/bindings/net/sff,sfp.yaml}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]9rough-guide-to-converting-a-network-driver-to-sfp-phylinkah ]h"]9rough guide to converting a network driver to sfp/phylinkah$]h&]uh1hhhhhhhhKFubeh}(h]phylinkah ]h"]phylinkah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksjFfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourcehnj _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jjjjjjjju nametypes}(jjjjuh}(jhjhjjjju footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages]transform_messages] transformerN include_log] decorationNhhub.