diff options
-rw-r--r-- | Documentation/networking/index.rst | 1 | ||||
-rw-r--r-- | Documentation/networking/sfp-phylink.rst | 268 |
2 files changed, 269 insertions, 0 deletions
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst index 9a32451cd201..b08cf145d5eb 100644 --- a/Documentation/networking/index.rst +++ b/Documentation/networking/index.rst | |||
@@ -31,6 +31,7 @@ Contents: | |||
31 | failover | 31 | failover |
32 | net_failover | 32 | net_failover |
33 | phy | 33 | phy |
34 | sfp-phylink | ||
34 | alias | 35 | alias |
35 | bridge | 36 | bridge |
36 | snmp_counter | 37 | snmp_counter |
diff --git a/Documentation/networking/sfp-phylink.rst b/Documentation/networking/sfp-phylink.rst new file mode 100644 index 000000000000..5bd26cb07244 --- /dev/null +++ b/Documentation/networking/sfp-phylink.rst | |||
@@ -0,0 +1,268 @@ | |||
1 | .. SPDX-License-Identifier: GPL-2.0 | ||
2 | |||
3 | ======= | ||
4 | phylink | ||
5 | ======= | ||
6 | |||
7 | Overview | ||
8 | ======== | ||
9 | |||
10 | phylink is a mechanism to support hot-pluggable networking modules | ||
11 | without needing to re-initialise the adapter on hot-plug events. | ||
12 | |||
13 | phylink supports conventional phylib-based setups, fixed link setups | ||
14 | and SFP (Small Formfactor Pluggable) modules at present. | ||
15 | |||
16 | Modes of operation | ||
17 | ================== | ||
18 | |||
19 | phylink has several modes of operation, which depend on the firmware | ||
20 | settings. | ||
21 | |||
22 | 1. PHY mode | ||
23 | |||
24 | In PHY mode, we use phylib to read the current link settings from | ||
25 | the PHY, and pass them to the MAC driver. We expect the MAC driver | ||
26 | to configure exactly the modes that are specified without any | ||
27 | negotiation being enabled on the link. | ||
28 | |||
29 | 2. Fixed mode | ||
30 | |||
31 | Fixed mode is the same as PHY mode as far as the MAC driver is | ||
32 | concerned. | ||
33 | |||
34 | 3. In-band mode | ||
35 | |||
36 | In-band mode is used with 802.3z, SGMII and similar interface modes, | ||
37 | and we are expecting to use and honor the in-band negotiation or | ||
38 | control word sent across the serdes channel. | ||
39 | |||
40 | By example, what this means is that: | ||
41 | |||
42 | .. code-block:: none | ||
43 | |||
44 | ð { | ||
45 | phy = <&phy>; | ||
46 | phy-mode = "sgmii"; | ||
47 | }; | ||
48 | |||
49 | does not use in-band SGMII signalling. The PHY is expected to follow | ||
50 | exactly the settings given to it in its :c:func:`mac_config` function. | ||
51 | The link should be forced up or down appropriately in the | ||
52 | :c:func:`mac_link_up` and :c:func:`mac_link_down` functions. | ||
53 | |||
54 | .. code-block:: none | ||
55 | |||
56 | ð { | ||
57 | managed = "in-band-status"; | ||
58 | phy = <&phy>; | ||
59 | phy-mode = "sgmii"; | ||
60 | }; | ||
61 | |||
62 | uses in-band mode, where results from the PHY's negotiation are passed | ||
63 | to the MAC through the SGMII control word, and the MAC is expected to | ||
64 | acknowledge the control word. The :c:func:`mac_link_up` and | ||
65 | :c:func:`mac_link_down` functions must not force the MAC side link | ||
66 | up and down. | ||
67 | |||
68 | Rough guide to converting a network driver to sfp/phylink | ||
69 | ========================================================= | ||
70 | |||
71 | This guide briefly describes how to convert a network driver from | ||
72 | phylib to the sfp/phylink support. Please send patches to improve | ||
73 | this documentation. | ||
74 | |||
75 | 1. Optionally split the network driver's phylib update function into | ||
76 | three parts dealing with link-down, link-up and reconfiguring the | ||
77 | MAC settings. This can be done as a separate preparation commit. | ||
78 | |||
79 | An example of this preparation can be found in git commit fc548b991fb0. | ||
80 | |||
81 | 2. Replace:: | ||
82 | |||
83 | select FIXED_PHY | ||
84 | select PHYLIB | ||
85 | |||
86 | with:: | ||
87 | |||
88 | select PHYLINK | ||
89 | |||
90 | in the driver's Kconfig stanza. | ||
91 | |||
92 | 3. Add:: | ||
93 | |||
94 | #include <linux/phylink.h> | ||
95 | |||
96 | to the driver's list of header files. | ||
97 | |||
98 | 4. Add:: | ||
99 | |||
100 | struct phylink *phylink; | ||
101 | |||
102 | to the driver's private data structure. We shall refer to the | ||
103 | driver's private data pointer as ``priv`` below, and the driver's | ||
104 | private data structure as ``struct foo_priv``. | ||
105 | |||
106 | 5. Replace the following functions: | ||
107 | |||
108 | .. flat-table:: | ||
109 | :header-rows: 1 | ||
110 | :widths: 1 1 | ||
111 | :stub-columns: 0 | ||
112 | |||
113 | * - Original function | ||
114 | - Replacement function | ||
115 | * - phy_start(phydev) | ||
116 | - phylink_start(priv->phylink) | ||
117 | * - phy_stop(phydev) | ||
118 | - phylink_stop(priv->phylink) | ||
119 | * - phy_mii_ioctl(phydev, ifr, cmd) | ||
120 | - phylink_mii_ioctl(priv->phylink, ifr, cmd) | ||
121 | * - phy_ethtool_get_wol(phydev, wol) | ||
122 | - phylink_ethtool_get_wol(priv->phylink, wol) | ||
123 | * - phy_ethtool_set_wol(phydev, wol) | ||
124 | - phylink_ethtool_set_wol(priv->phylink, wol) | ||
125 | * - phy_disconnect(phydev) | ||
126 | - phylink_disconnect_phy(priv->phylink) | ||
127 | |||
128 | Please note that some of these functions must be called under the | ||
129 | rtnl lock, and will warn if not. This will normally be the case, | ||
130 | except if these are called from the driver suspend/resume paths. | ||
131 | |||
132 | 6. Add/replace ksettings get/set methods with: | ||
133 | |||
134 | .. code-block:: c | ||
135 | |||
136 | static int foo_ethtool_set_link_ksettings(struct net_device *dev, | ||
137 | const struct ethtool_link_ksettings *cmd) | ||
138 | { | ||
139 | struct foo_priv *priv = netdev_priv(dev); | ||
140 | |||
141 | return phylink_ethtool_ksettings_set(priv->phylink, cmd); | ||
142 | } | ||
143 | |||
144 | static int foo_ethtool_get_link_ksettings(struct net_device *dev, | ||
145 | struct ethtool_link_ksettings *cmd) | ||
146 | { | ||
147 | struct foo_priv *priv = netdev_priv(dev); | ||
148 | |||
149 | return phylink_ethtool_ksettings_get(priv->phylink, cmd); | ||
150 | } | ||
151 | |||
152 | 7. Replace the call to: | ||
153 | |||
154 | phy_dev = of_phy_connect(dev, node, link_func, flags, phy_interface); | ||
155 | |||
156 | and associated code with a call to: | ||
157 | |||
158 | err = phylink_of_phy_connect(priv->phylink, node, flags); | ||
159 | |||
160 | For the most part, ``flags`` can be zero; these flags are passed to | ||
161 | the of_phy_attach() inside this function call if a PHY is specified | ||
162 | in the DT node ``node``. | ||
163 | |||
164 | ``node`` should be the DT node which contains the network phy property, | ||
165 | fixed link properties, and will also contain the sfp property. | ||
166 | |||
167 | The setup of fixed links should also be removed; these are handled | ||
168 | internally by phylink. | ||
169 | |||
170 | of_phy_connect() was also passed a function pointer for link updates. | ||
171 | This function is replaced by a different form of MAC updates | ||
172 | described below in (8). | ||
173 | |||
174 | Manipulation of the PHY's supported/advertised happens within phylink | ||
175 | based on the validate callback, see below in (8). | ||
176 | |||
177 | Note that the driver no longer needs to store the ``phy_interface``, | ||
178 | and also note that ``phy_interface`` becomes a dynamic property, | ||
179 | just like the speed, duplex etc. settings. | ||
180 | |||
181 | Finally, note that the MAC driver has no direct access to the PHY | ||
182 | anymore; that is because in the phylink model, the PHY can be | ||
183 | dynamic. | ||
184 | |||
185 | 8. Add a :c:type:`struct phylink_mac_ops <phylink_mac_ops>` instance to | ||
186 | the driver, which is a table of function pointers, and implement | ||
187 | these functions. The old link update function for | ||
188 | :c:func:`of_phy_connect` becomes three methods: :c:func:`mac_link_up`, | ||
189 | :c:func:`mac_link_down`, and :c:func:`mac_config`. If step 1 was | ||
190 | performed, then the functionality will have been split there. | ||
191 | |||
192 | It is important that if in-band negotiation is used, | ||
193 | :c:func:`mac_link_up` and :c:func:`mac_link_down` do not prevent the | ||
194 | in-band negotiation from completing, since these functions are called | ||
195 | when the in-band link state changes - otherwise the link will never | ||
196 | come up. | ||
197 | |||
198 | The :c:func:`validate` method should mask the supplied supported mask, | ||
199 | and ``state->advertising`` with the supported ethtool link modes. | ||
200 | These are the new ethtool link modes, so bitmask operations must be | ||
201 | used. For an example, see drivers/net/ethernet/marvell/mvneta.c. | ||
202 | |||
203 | The :c:func:`mac_link_state` method is used to read the link state | ||
204 | from the MAC, and report back the settings that the MAC is currently | ||
205 | using. This is particularly important for in-band negotiation | ||
206 | methods such as 1000base-X and SGMII. | ||
207 | |||
208 | The :c:func:`mac_config` method is used to update the MAC with the | ||
209 | requested state, and must avoid unnecessarily taking the link down | ||
210 | when making changes to the MAC configuration. This means the | ||
211 | function should modify the state and only take the link down when | ||
212 | absolutely necessary to change the MAC configuration. An example | ||
213 | of how to do this can be found in :c:func:`mvneta_mac_config` in | ||
214 | drivers/net/ethernet/marvell/mvneta.c. | ||
215 | |||
216 | For further information on these methods, please see the inline | ||
217 | documentation in :c:type:`struct phylink_mac_ops <phylink_mac_ops>`. | ||
218 | |||
219 | 9. Remove calls to of_parse_phandle() for the PHY, | ||
220 | of_phy_register_fixed_link() for fixed links etc. from the probe | ||
221 | function, and replace with: | ||
222 | |||
223 | .. code-block:: c | ||
224 | |||
225 | struct phylink *phylink; | ||
226 | |||
227 | phylink = phylink_create(dev, node, phy_mode, &phylink_ops); | ||
228 | if (IS_ERR(phylink)) { | ||
229 | err = PTR_ERR(phylink); | ||
230 | fail probe; | ||
231 | } | ||
232 | |||
233 | priv->phylink = phylink; | ||
234 | |||
235 | and arrange to destroy the phylink in the probe failure path as | ||
236 | appropriate and the removal path too by calling: | ||
237 | |||
238 | .. code-block:: c | ||
239 | |||
240 | phylink_destroy(priv->phylink); | ||
241 | |||
242 | 10. Arrange for MAC link state interrupts to be forwarded into | ||
243 | phylink, via: | ||
244 | |||
245 | .. code-block:: c | ||
246 | |||
247 | phylink_mac_change(priv->phylink, link_is_up); | ||
248 | |||
249 | where ``link_is_up`` is true if the link is currently up or false | ||
250 | otherwise. | ||
251 | |||
252 | 11. Verify that the driver does not call:: | ||
253 | |||
254 | netif_carrier_on() | ||
255 | netif_carrier_off() | ||
256 | |||
257 | as these will interfere with phylink's tracking of the link state, | ||
258 | and cause phylink to omit calls via the :c:func:`mac_link_up` and | ||
259 | :c:func:`mac_link_down` methods. | ||
260 | |||
261 | Network drivers should call phylink_stop() and phylink_start() via their | ||
262 | suspend/resume paths, which ensures that the appropriate | ||
263 | :c:type:`struct phylink_mac_ops <phylink_mac_ops>` methods are called | ||
264 | as necessary. | ||
265 | |||
266 | For information describing the SFP cage in DT, please see the binding | ||
267 | documentation in the kernel source tree | ||
268 | ``Documentation/devicetree/bindings/net/sff,sfp.txt`` | ||