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]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.}(hjhhhNhNubah}(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.}(hj8hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj&ubeh}(h]h ]h"]h$]h&]uh1j$hj!hhhhhNubj%)}(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}(hjPhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjLubh)}(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.}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hjLubeh}(h]h ]h"]h$]h&]uh1j$hj!hhhhhNubj%)}(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}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK#hjrubh)}(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%hjrubeh}(h]h ]h"]h$]h&]uh1j$hj!hhhhhNubeh}(h]h ]h"]h$]h&]enumtypearabicprefixhsuffix.uh1jhjhhhhhKubh)}(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&]hhforcelanguagenonehighlight_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)}(hjh]h mac_link_up()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhK2hjubh and }(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_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"; };}hjCsbah}(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 }(hjShhhNhNubh)}(h:c:func:`mac_link_up`h]j)}(hj]h]h mac_link_up()}(hj_hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj[ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhK?hjSubh and }(hjShhhNhNubh)}(h:c:func:`mac_link_down`h]j)}(hjh]hmac_link_down()}(hjhhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj~ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_downuh1hhhhK?hjSubh8 functions must not force the MAC side link up and down.}(hjShhhNhNubeh}(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&]uh1hhhhKHhjhhubj )}(hhh](j%)}(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&]uh1j$hjhhhhhNubj%)}(hrReplace:: select FIXED_PHY select PHYLIB with:: select PHYLINK in the driver's Kconfig stanza. h](h)}(h Replace::h]hReplace:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKUhjubj)}(hselect FIXED_PHY select PHYLIBh]hselect FIXED_PHY select PHYLIB}hj,sbah}(h]h ]h"]h$]h&]hhuh1jhhhKWhjubh)}(hwith::h]hwith:}(hj:hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKZhjubj)}(hselect PHYLINKh]hselect PHYLINK}hjHsbah}(h]h ]h"]h$]h&]hhuh1jhhhK\hjubh)}(hin the driver's Kconfig stanza.h]h!in the driver’s Kconfig stanza.}(hjVhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK^hjubeh}(h]h ]h"]h$]h&]uh1j$hjhhhhhNubj%)}(hNAdd:: #include to the driver's list of header files. h](h)}(hAdd::h]hAdd:}(hjnhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK`hjjubj)}(h#include h]h#include }hj|sbah}(h]h ]h"]h$]h&]hhuh1jhhhKbhjjubh)}(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&]uh1hhhhKdhjjubeh}(h]h ]h"]h$]h&]uh1j$hjhhhhhNubj%)}(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&]uh1j$hjhhhhhNubj%)}(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&]uh1hhhhKohjubhtable)}(hhh]htgroup)}(hhh](hcolspec)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1jhjubhthead)}(hhh]hrow)}(hhh](hentry)}(hhh]h)}(hOriginal functionh]hOriginal function}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKvhj4ubah}(h]h ]h"]h$]h&]uh1j2hj/ubj3)}(hhh]h)}(hReplacement functionh]hReplacement function}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKwhjKubah}(h]h ]h"]h$]h&]uh1j2hj/ubeh}(h]h ]h"]h$]h&]uh1j-hj*ubah}(h]h ]h"]h$]h&]uh1j(hjubhtbody)}(hhh](j.)}(hhh](j3)}(hhh]h)}(hphy_start(phydev)h]hphy_start(phydev)}(hjyhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKxhjvubah}(h]h ]h"]h$]h&]uh1j2hjsubj3)}(hhh]h)}(hphylink_start(priv->phylink)h]hphylink_start(priv->phylink)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKyhjubah}(h]h ]h"]h$]h&]uh1j2hjsubeh}(h]h ]h"]h$]h&]uh1j-hjpubj.)}(hhh](j3)}(hhh]h)}(hphy_stop(phydev)h]hphy_stop(phydev)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKzhjubah}(h]h ]h"]h$]h&]uh1j2hjubj3)}(hhh]h)}(hphylink_stop(priv->phylink)h]hphylink_stop(priv->phylink)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK{hjubah}(h]h ]h"]h$]h&]uh1j2hjubeh}(h]h ]h"]h$]h&]uh1j-hjpubj.)}(hhh](j3)}(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&]uh1j2hjubj3)}(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&]uh1j2hjubeh}(h]h ]h"]h$]h&]uh1j-hjpubj.)}(hhh](j3)}(hhh]h)}(h phy_ethtool_get_wol(phydev, wol)h]h phy_ethtool_get_wol(phydev, wol)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK~hjubah}(h]h ]h"]h$]h&]uh1j2hjubj3)}(hhh]h)}(h+phylink_ethtool_get_wol(priv->phylink, wol)h]h+phylink_ethtool_get_wol(priv->phylink, wol)}(hj5hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj2ubah}(h]h ]h"]h$]h&]uh1j2hjubeh}(h]h ]h"]h$]h&]uh1j-hjpubj.)}(hhh](j3)}(hhh]h)}(h phy_ethtool_set_wol(phydev, wol)h]h phy_ethtool_set_wol(phydev, wol)}(hjUhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjRubah}(h]h ]h"]h$]h&]uh1j2hjOubj3)}(hhh]h)}(h+phylink_ethtool_set_wol(priv->phylink, wol)h]h+phylink_ethtool_set_wol(priv->phylink, wol)}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjiubah}(h]h ]h"]h$]h&]uh1j2hjOubeh}(h]h ]h"]h$]h&]uh1j-hjpubj.)}(hhh](j3)}(hhh]h)}(hphy_disconnect(phydev)h]hphy_disconnect(phydev)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1j2hjubj3)}(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&]uh1j2hjubeh}(h]h ]h"]h$]h&]uh1j-hjpubeh}(h]h ]h"]h$]h&]uh1jnhjubeh}(h]h ]h"]h$]h&]colsKuh1j hj ubah}(h]h ]h"]h$]h&]uh1jhjubh)}(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&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1j$hjhhhhhNubj%)}(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); }}hjsbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhKhjubeh}(h]h ]h"]h$]h&]uh1j$hjhhhNhNubj%)}(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:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubj)}(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);}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj ubh)}(h$and associated code with a call to::h]h#and associated code with a call to:}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubj)}(h9err = phylink_of_phy_connect(priv->phylink, node, flags);h]h9err = phylink_of_phy_connect(priv->phylink, node, flags);}hj9sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj ubh)}(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, }(hjGhhhNhNubj)}(h ``flags``h]hflags}(hjOhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjGubh 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 }(hjGhhhNhNubj)}(h``node``h]hnode}(hjahhhNhNubah}(h]h ]h"]h$]h&]uh1jhjGubh.}(hjGhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubh)}(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}(hj}hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjyubh~ should be the DT node which contains the network phy property, fixed link properties, and will also contain the sfp property.}(hjyhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubh)}(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&]uh1hhhhKhj ubh)}(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&]uh1hhhhKhj ubh)}(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&]uh1hhhhKhj ubh)}(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&]uh1hhhhKhj ubh)}(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&]uh1hhhhKhj ubeh}(h]h ]h"]h$]h&]uh1j$hjhhhhhNubj%)}(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 }(hj hhhNhNubh)}(h2:c:type:`struct phylink_mac_ops `h]j)}(hjh]hstruct phylink_mac_ops}(hjhhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_mac_opsuh1hhhhKhj ubh instance to the driver, which is a table of function pointers, and implement these functions. The old link update function for }(hj hhhNhNubh)}(h:c:func:`of_phy_connect`h]j)}(hj6h]hof_phy_connect()}(hj8hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj4ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnjof_phy_connectuh1hhhhKhj ubh becomes three methods: }(hj hhhNhNubh)}(h:c:func:`mac_link_up`h]j)}(hjYh]h mac_link_up()}(hj[hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjWubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhKhj ubh, }(hj hhhNhNubh)}(h:c:func:`mac_link_down`h]j)}(hj|h]hmac_link_down()}(hj~hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjzubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_downuh1hhhhKhj ubh, and }(hj hhhNhNubh)}(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_configuh1hhhhKhj ubhM. If step 1 was performed, then the functionality will have been split there.}(hj hhhNhNubeh}(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()}(hjhhhNhNubah}(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 }(hjhhhNhNubh)}(h:c:func:`mac_get_caps`h]j)}(hj$h]hmac_get_caps()}(hj&hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj"ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_get_capsuh1hhhhKhjubhr method is optional, and if provided should return the phylink MAC capabilities that are supported for the passed }(hjhhhNhNubj)}(h ``interface``h]h interface}(hjEhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh mode. In general, there is no need to implement this method. Phylink will use these capabilities in combination with permissible capabilities for }(hjhhhNhNubj)}(h ``interface``h]h interface}(hjWhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh/ to determine the allowable ethtool link modes.}(hjhhhNhNubeh}(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 }(hjohhhNhNubh)}(h:c:func:`mac_link_state`h]j)}(hjyh]hmac_link_state()}(hj{hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjwubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnjmac_link_stateuh1hhhhKhjoubh 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.}(hjohhhNhNubeh}(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)}(hjh]hmvneta_mac_config()}(hj hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhjubah}(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}(hj 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 }(hj7 hhhNhNubh)}(h2:c:type:`struct phylink_mac_ops `h]j)}(hjA h]hstruct phylink_mac_ops}(hjC hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj? ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_mac_opsuh1hhhhKhj7 ubh.}(hj7 hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1j$hjhhhhhNubj%)}(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 }(hjr hhhNhNubh)}(h0:c:type:`struct phylink_config `h]j)}(hj| h]hstruct phylink_config}(hj~ hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhjz ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_configuh1hhhhKhjr ubh fields with a reference to the }(hjr 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 refexplicitrefwarnjdeviceuh1hhhhKhjr ubh associated to your }(hjr 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_deviceuh1hhhhKhjr ubh:}(hjr hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjn 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}uh1jhhhKhjn 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&]uh1hhhhKhjn 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}uh1jhhhKhjn ubeh}(h]h ]h"]h$]h&]uh1j$hjhhhNhNubj%)}(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 }(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_pcsuh1hhhhKhj ubh.}(hj 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.}(hjP 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.}(hj^ 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 }(hjl hhhNhNubh)}(h*:c:type:`struct phylink_pcs `h]j)}(hjv h]hstruct phylink_pcs}(hjx hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhjt ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnj phylink_pcsuh1hhhhMhjl ubhF instance per PCS block within your driver’s private data structure:}(hjl 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)}(hj h]hpcs_validate()}(hj! hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj 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, };}hjF 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:}(hjU 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);}hjc 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 }(hjr hhhNhNubj)}(h``link_is_up``h]h link_is_up}(hjz hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjr 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 }(hjr hhhNhNubj)}(h``pcs->pcs_poll = true;``h]hpcs->pcs_poll = true;}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjr ubh when creating the PCS.}(hjr hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM$hj ubeh}(h]h ]h"]h$]h&]uh1j$hjhhhhhNubj%)}(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&]uh1j$hjhhhNhNubj%)}(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 }(hj2 hhhNhNubh)}(h:c:func:`mac_select_pcs`h]j)}(hj< h]hmac_select_pcs()}(hj> hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj: ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnjmac_select_pcsuh1hhhhM@hj2 ubh callback and add it to your }(hj2 hhhNhNubh)}(h2:c:type:`struct phylink_mac_ops `h]j)}(hj_ h]hstruct phylink_mac_ops}(hja hhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhj] ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_mac_opsuh1hhhhM@hj2 ubhA set of ops. This function must return a pointer to the relevant }(hj2 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@hj2 ubh8 that will be used for the requested link configuration:}(hj2 hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM@hj. 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}uh1jhhhMEhj. 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&]uh1hhhhMShj. ubeh}(h]h ]h"]h$]h&]uh1j$hjhhhhhNubj%)}(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);}hj$ sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhM\hj ubeh}(h]h ]h"]h$]h&]uh1j$hjhhhNhNubj%)}(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:}(hj= hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMdhj9 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;}hjK sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhMhhj9 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:}(hjZ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMthj9 ubj)}(hphylink_destroy(priv->phylink);h]hphylink_destroy(priv->phylink);}hjh sbah}(h]h ]h"]h$]h&]hhjjjj}uh1jhhhMwhj9 ubeh}(h]h ]h"]h$]h&]uh1j$hjhhhNhNubj%)}(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&]uh1j$hjhhhhhNubj%)}(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)}(hj h]h mac_link_up()}(hj hhhNhNubah}(h]h ](jjc-funceh"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypefunc refexplicitrefwarnj mac_link_upuh1hhhhMhj ubh and }(hj hhhNhNubh)}(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_downuh1hhhhMhj ubh methods.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubeh}(h]h ]h"]h$]h&]uh1j$hjhhhhhNubeh}(h]h ]h"]h$]h&]jjjhjjuh1jhjhhhhhKLubh)}(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 }(hjDhhhNhNubh)}(h2:c:type:`struct phylink_mac_ops `h]j)}(hjNh]hstruct phylink_mac_ops}(hjPhhhNhNubah}(h]h ](jjc-typeeh"]h$]h&]uh1jhjLubah}(h]h ]h"]h$]h&]refdocj refdomainjreftypetype refexplicitrefwarnjphylink_mac_opsuh1hhhhMhjDubh! methods are called as necessary.}(hjDhhhNhNubeh}(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 }(hjuhhhNhNubj)}(h6``Documentation/devicetree/bindings/net/sff,sfp.yaml``h]h2Documentation/devicetree/bindings/net/sff,sfp.yaml}(hj}hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjuubh.}(hjuhhhNhNubeh}(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_backlinksj2footnote_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_sourceh _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}(jjhhjjjju nametypes}(jhjjuh}(jhhhjjjju 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.