739-net-add-negotiation-of-in-band-capabilities.patch 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  1. From: "Russell King (Oracle)" <[email protected]>
  2. To: Andrew Lunn <[email protected]>, Heiner Kallweit <[email protected]>
  3. Cc: Alexander Couzens <[email protected]>,
  4. Andrew Lunn <[email protected]>,
  5. AngeloGioacchino Del Regno
  6. <[email protected]>,
  7. Broadcom internal kernel review list
  8. <[email protected]>,
  9. Daniel Golle <[email protected]>,
  10. "David S. Miller" <[email protected]>,
  11. Eric Dumazet <[email protected]>,
  12. Florian Fainelli <[email protected]>,
  13. Ioana Ciornei <[email protected]>,
  14. Jakub Kicinski <[email protected]>,
  15. Jose Abreu <[email protected]>,
  16. [email protected],
  17. [email protected],
  18. Marcin Wojtas <[email protected]>,
  19. Matthias Brugger <[email protected]>,
  20. [email protected], Paolo Abeni <[email protected]>
  21. Subject: [PATCH RFC net-next 00/16] net: add negotiation of in-band capabilities
  22. Date: Tue, 26 Nov 2024 09:23:48 +0000 [thread overview]
  23. Message-ID: <[email protected]> (raw)
  24. Hi,
  25. Yes, this is one patch over the limit of 15 for netdev - but I think it's
  26. important to include the last patch to head off review comments like "why
  27. don't you remove phylink_phy_no_inband() in this series?"
  28. Phylink's handling of in-band has been deficient for a long time, and
  29. people keep hitting problems with it. Notably, situations with the way-
  30. to-late standardized 2500Base-X and whether that should or should not
  31. have in-band enabled. We have also been carrying a hack in the form of
  32. phylink_phy_no_inband() for a PHY that has been used on a SFP module,
  33. but has no in-band capabilities, not even for SGMII.
  34. When phylink is trying to operate in in-band mode, this series will look
  35. at the capabilities of the MAC-side PCS and PHY, and work out whether
  36. in-band can or should be used, programming the PHY as appropriate. This
  37. includes in-band bypass mode at the PHY.
  38. We don't... yet... support that on the MAC side PCS, because that
  39. requires yet more complexity.
  40. Patch 1 passes struct phylink and struct phylink_pcs into
  41. phylink_pcs_neg_mode() so we can look at more state in this function in
  42. a future patch.
  43. Patch 2 splits "cur_link_an_mode" (the MLO_AN_* mode) into two separate
  44. purposes - a requested and an active mode. The active mode is the one
  45. we will be using for the MAC, which becomes dependent on the result of
  46. in-band negotiation.
  47. Patch 3 adds debug to phylink_major_config() so we can see what is going
  48. on with the requested and active AN modes.
  49. Patch 4 adds to phylib a method to get the in-band capabilities of the
  50. PHY from phylib. Patches 5 and 6 add implementations for BCM84881 and
  51. some Marvell PHYs found on SFPs.
  52. Patch 7 adds to phylib a method to configure the PHY in-band signalling,
  53. and patch 8 implements it for those Marvell PHYs that support the method
  54. in patch 4.
  55. Patch 9 does the same as patch 4 but for the MAC-side PCS, with patches
  56. 10 through 14 adding support to several PCS.
  57. Patch 15 adds the code to phylink_pcs_neg_mode() which looks at the
  58. capabilities, and works out whether to use in-band or out-band mode for
  59. driving the link between the MAC PCS and PHY.
  60. Patch 16 removes the phylink_phy_no_inband() hack now that we are
  61. publishing the in-band capabilities from the BCM84881 PHY driver.
  62. drivers/net/ethernet/marvell/mvneta.c | 27 +-
  63. drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 25 +-
  64. drivers/net/pcs/pcs-lynx.c | 22 ++
  65. drivers/net/pcs/pcs-mtk-lynxi.c | 16 ++
  66. drivers/net/pcs/pcs-xpcs.c | 28 ++
  67. drivers/net/phy/bcm84881.c | 10 +
  68. drivers/net/phy/marvell.c | 48 ++++
  69. drivers/net/phy/phy.c | 52 ++++
  70. drivers/net/phy/phylink.c | 352 +++++++++++++++++++-----
  71. include/linux/phy.h | 34 +++
  72. include/linux/phylink.h | 17 ++
  73. 11 files changed, 539 insertions(+), 92 deletions(-)
  74. --- a/drivers/net/phy/phylink.c
  75. +++ b/drivers/net/phy/phylink.c
  76. @@ -56,7 +56,8 @@ struct phylink {
  77. struct phy_device *phydev;
  78. phy_interface_t link_interface; /* PHY_INTERFACE_xxx */
  79. u8 cfg_link_an_mode; /* MLO_AN_xxx */
  80. - u8 cur_link_an_mode;
  81. + u8 req_link_an_mode; /* Requested MLO_AN_xxx mode */
  82. + u8 act_link_an_mode; /* Active MLO_AN_xxx mode */
  83. u8 link_port; /* The current non-phy ethtool port */
  84. __ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
  85. @@ -74,6 +75,7 @@ struct phylink {
  86. struct mutex state_mutex;
  87. struct phylink_link_state phy_state;
  88. + unsigned int phy_ib_mode;
  89. struct work_struct resolve;
  90. unsigned int pcs_neg_mode;
  91. unsigned int pcs_state;
  92. @@ -175,6 +177,24 @@ static const char *phylink_an_mode_str(u
  93. return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
  94. }
  95. +static const char *phylink_pcs_mode_str(unsigned int mode)
  96. +{
  97. + if (!mode)
  98. + return "none";
  99. +
  100. + if (mode & PHYLINK_PCS_NEG_OUTBAND)
  101. + return "outband";
  102. +
  103. + if (mode & PHYLINK_PCS_NEG_INBAND) {
  104. + if (mode & PHYLINK_PCS_NEG_ENABLED)
  105. + return "inband,an-enabled";
  106. + else
  107. + return "inband,an-disabled";
  108. + }
  109. +
  110. + return "unknown";
  111. +}
  112. +
  113. static unsigned int phylink_interface_signal_rate(phy_interface_t interface)
  114. {
  115. switch (interface) {
  116. @@ -1053,6 +1073,15 @@ static void phylink_resolve_an_pause(str
  117. }
  118. }
  119. +static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs,
  120. + phy_interface_t interface)
  121. +{
  122. + if (pcs && pcs->ops->pcs_inband_caps)
  123. + return pcs->ops->pcs_inband_caps(pcs, interface);
  124. +
  125. + return 0;
  126. +}
  127. +
  128. static void phylink_pcs_pre_config(struct phylink_pcs *pcs,
  129. phy_interface_t interface)
  130. {
  131. @@ -1106,6 +1135,24 @@ static void phylink_pcs_link_up(struct p
  132. pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex);
  133. }
  134. +/* Query inband for a specific interface mode, asking the MAC for the
  135. + * PCS which will be used to handle the interface mode.
  136. + */
  137. +static unsigned int phylink_inband_caps(struct phylink *pl,
  138. + phy_interface_t interface)
  139. +{
  140. + struct phylink_pcs *pcs;
  141. +
  142. + if (!pl->mac_ops->mac_select_pcs)
  143. + return 0;
  144. +
  145. + pcs = pl->mac_ops->mac_select_pcs(pl->config, interface);
  146. + if (!pcs)
  147. + return 0;
  148. +
  149. + return phylink_pcs_inband_caps(pcs, interface);
  150. +}
  151. +
  152. static void phylink_pcs_poll_stop(struct phylink *pl)
  153. {
  154. if (pl->cfg_link_an_mode == MLO_AN_INBAND)
  155. @@ -1132,13 +1179,13 @@ static void phylink_mac_config(struct ph
  156. phylink_dbg(pl,
  157. "%s: mode=%s/%s/%s adv=%*pb pause=%02x\n",
  158. - __func__, phylink_an_mode_str(pl->cur_link_an_mode),
  159. + __func__, phylink_an_mode_str(pl->act_link_an_mode),
  160. phy_modes(st.interface),
  161. phy_rate_matching_to_str(st.rate_matching),
  162. __ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising,
  163. st.pause);
  164. - pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st);
  165. + pl->mac_ops->mac_config(pl->config, pl->act_link_an_mode, &st);
  166. }
  167. static void phylink_pcs_an_restart(struct phylink *pl)
  168. @@ -1146,13 +1193,14 @@ static void phylink_pcs_an_restart(struc
  169. if (pl->pcs && linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
  170. pl->link_config.advertising) &&
  171. phy_interface_mode_is_8023z(pl->link_config.interface) &&
  172. - phylink_autoneg_inband(pl->cur_link_an_mode))
  173. + phylink_autoneg_inband(pl->act_link_an_mode))
  174. pl->pcs->ops->pcs_an_restart(pl->pcs);
  175. }
  176. /**
  177. * phylink_pcs_neg_mode() - helper to determine PCS inband mode
  178. - * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
  179. + * @pl: a pointer to a &struct phylink returned from phylink_create()
  180. + * @pcs: a pointer to &struct phylink_pcs
  181. * @interface: interface mode to be used
  182. * @advertising: adertisement ethtool link mode mask
  183. *
  184. @@ -1169,11 +1217,21 @@ static void phylink_pcs_an_restart(struc
  185. * Note: this is for cases where the PCS itself is involved in negotiation
  186. * (e.g. Clause 37, SGMII and similar) not Clause 73.
  187. */
  188. -static unsigned int phylink_pcs_neg_mode(unsigned int mode,
  189. - phy_interface_t interface,
  190. - const unsigned long *advertising)
  191. +static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
  192. + phy_interface_t interface,
  193. + const unsigned long *advertising)
  194. {
  195. - unsigned int neg_mode;
  196. + unsigned int pcs_ib_caps = 0;
  197. + unsigned int phy_ib_caps = 0;
  198. + unsigned int neg_mode, mode;
  199. + enum {
  200. + INBAND_CISCO_SGMII,
  201. + INBAND_BASEX,
  202. + } type;
  203. +
  204. + mode = pl->req_link_an_mode;
  205. +
  206. + pl->phy_ib_mode = 0;
  207. switch (interface) {
  208. case PHY_INTERFACE_MODE_SGMII:
  209. @@ -1185,10 +1243,7 @@ static unsigned int phylink_pcs_neg_mode
  210. * inband communication. Note: there exist PHYs that run
  211. * with SGMII but do not send the inband data.
  212. */
  213. - if (!phylink_autoneg_inband(mode))
  214. - neg_mode = PHYLINK_PCS_NEG_OUTBAND;
  215. - else
  216. - neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
  217. + type = INBAND_CISCO_SGMII;
  218. break;
  219. case PHY_INTERFACE_MODE_1000BASEX:
  220. @@ -1199,21 +1254,143 @@ static unsigned int phylink_pcs_neg_mode
  221. * as well, but drivers may not support this, so may
  222. * need to override this.
  223. */
  224. - if (!phylink_autoneg_inband(mode))
  225. + type = INBAND_BASEX;
  226. + break;
  227. +
  228. + default:
  229. + pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE;
  230. + pl->act_link_an_mode = mode;
  231. + return;
  232. + }
  233. +
  234. + if (pcs)
  235. + pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface);
  236. +
  237. + if (pl->phydev)
  238. + phy_ib_caps = phy_inband_caps(pl->phydev, interface);
  239. +
  240. + phylink_dbg(pl, "interface %s inband modes: pcs=%02x phy=%02x\n",
  241. + phy_modes(interface), pcs_ib_caps, phy_ib_caps);
  242. +
  243. + if (!phylink_autoneg_inband(mode)) {
  244. + bool pcs_ib_only = false;
  245. + bool phy_ib_only = false;
  246. +
  247. + if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE) {
  248. + /* PCS supports reporting in-band capabilities, and
  249. + * supports more than disable mode.
  250. + */
  251. + if (pcs_ib_caps & LINK_INBAND_DISABLE)
  252. + neg_mode = PHYLINK_PCS_NEG_OUTBAND;
  253. + else if (pcs_ib_caps & LINK_INBAND_ENABLE)
  254. + pcs_ib_only = true;
  255. + }
  256. +
  257. + if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE) {
  258. + /* PHY supports in-band capabilities, and supports
  259. + * more than disable mode.
  260. + */
  261. + if (phy_ib_caps & LINK_INBAND_DISABLE)
  262. + pl->phy_ib_mode = LINK_INBAND_DISABLE;
  263. + else if (phy_ib_caps & LINK_INBAND_BYPASS)
  264. + pl->phy_ib_mode = LINK_INBAND_BYPASS;
  265. + else if (phy_ib_caps & LINK_INBAND_ENABLE)
  266. + phy_ib_only = true;
  267. + }
  268. +
  269. + /* If either the PCS or PHY requires inband to be enabled,
  270. + * this is an invalid configuration. Provide a diagnostic
  271. + * message for this case, but don't try to force the issue.
  272. + */
  273. + if (pcs_ib_only || phy_ib_only)
  274. + phylink_warn(pl,
  275. + "firmware wants %s mode, but %s%s%s requires inband\n",
  276. + phylink_an_mode_str(mode),
  277. + pcs_ib_only ? "PCS" : "",
  278. + pcs_ib_only && phy_ib_only ? " and " : "",
  279. + phy_ib_only ? "PHY" : "");
  280. +
  281. + neg_mode = PHYLINK_PCS_NEG_OUTBAND;
  282. + } else if (type == INBAND_CISCO_SGMII || pl->phydev) {
  283. + /* For SGMII modes which are designed to be used with PHYs, or
  284. + * Base-X with a PHY, we try to use in-band mode where-ever
  285. + * possible. However, there are some PHYs e.g. BCM84881 which
  286. + * do not support in-band.
  287. + */
  288. + const unsigned int inband_ok = LINK_INBAND_ENABLE |
  289. + LINK_INBAND_BYPASS;
  290. + const unsigned int outband_ok = LINK_INBAND_DISABLE |
  291. + LINK_INBAND_BYPASS;
  292. + /* PCS PHY
  293. + * D E D E
  294. + * 0 0 0 0 no information inband enabled
  295. + * 1 0 0 0 pcs doesn't support outband
  296. + * 0 1 0 0 pcs required inband enabled
  297. + * 1 1 0 0 pcs optional inband enabled
  298. + * 0 0 1 0 phy doesn't support outband
  299. + * 1 0 1 0 pcs+phy doesn't support outband
  300. + * 0 1 1 0 pcs required, phy doesn't support, invalid
  301. + * 1 1 1 0 pcs optional, phy doesn't support, outband
  302. + * 0 0 0 1 phy required inband enabled
  303. + * 1 0 0 1 pcs doesn't support, phy required, invalid
  304. + * 0 1 0 1 pcs+phy required inband enabled
  305. + * 1 1 0 1 pcs optional, phy required inband enabled
  306. + * 0 0 1 1 phy optional inband enabled
  307. + * 1 0 1 1 pcs doesn't support, phy optional, outband
  308. + * 0 1 1 1 pcs required, phy optional inband enabled
  309. + * 1 1 1 1 pcs+phy optional inband enabled
  310. + */
  311. + if ((!pcs_ib_caps || pcs_ib_caps & inband_ok) &&
  312. + (!phy_ib_caps || phy_ib_caps & inband_ok)) {
  313. + /* In-band supported or unknown at both ends. Enable
  314. + * in-band mode with or without bypass at the PHY.
  315. + */
  316. + if (phy_ib_caps & LINK_INBAND_ENABLE)
  317. + pl->phy_ib_mode = LINK_INBAND_ENABLE;
  318. + else if (phy_ib_caps & LINK_INBAND_BYPASS)
  319. + pl->phy_ib_mode = LINK_INBAND_BYPASS;
  320. +
  321. + neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
  322. + } else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok) &&
  323. + (!phy_ib_caps || phy_ib_caps & outband_ok)) {
  324. + /* Either in-band not supported at at least one end.
  325. + * In-band bypass at the other end is possible.
  326. + */
  327. + if (phy_ib_caps & LINK_INBAND_DISABLE)
  328. + pl->phy_ib_mode = LINK_INBAND_DISABLE;
  329. + else if (phy_ib_caps & LINK_INBAND_BYPASS)
  330. + pl->phy_ib_mode = LINK_INBAND_BYPASS;
  331. +
  332. neg_mode = PHYLINK_PCS_NEG_OUTBAND;
  333. + if (pl->phydev)
  334. + mode = MLO_AN_PHY;
  335. + } else {
  336. + /* invalid */
  337. + phylink_warn(pl, "%s: incompatible in-band capabilities, trying in-band",
  338. + phy_modes(interface));
  339. + neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
  340. + }
  341. + } else {
  342. + /* For Base-X without a PHY */
  343. + if (pcs_ib_caps == LINK_INBAND_DISABLE)
  344. + /* If the PCS doesn't support inband, then inband must
  345. + * be disabled.
  346. + */
  347. + neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
  348. + else if (pcs_ib_caps == LINK_INBAND_ENABLE)
  349. + /* If the PCS requires inband, then inband must always
  350. + * be enabled.
  351. + */
  352. + neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
  353. else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
  354. advertising))
  355. neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
  356. else
  357. neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
  358. - break;
  359. -
  360. - default:
  361. - neg_mode = PHYLINK_PCS_NEG_NONE;
  362. - break;
  363. }
  364. - return neg_mode;
  365. + pl->pcs_neg_mode = neg_mode;
  366. + pl->act_link_an_mode = mode;
  367. }
  368. static void phylink_major_config(struct phylink *pl, bool restart,
  369. @@ -1225,11 +1402,9 @@ static void phylink_major_config(struct
  370. unsigned int neg_mode;
  371. int err;
  372. - phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
  373. -
  374. - pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
  375. - state->interface,
  376. - state->advertising);
  377. + phylink_dbg(pl, "major config, requested %s/%s\n",
  378. + phylink_an_mode_str(pl->req_link_an_mode),
  379. + phy_modes(state->interface));
  380. if (pl->using_mac_select_pcs) {
  381. pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
  382. @@ -1243,10 +1418,17 @@ static void phylink_major_config(struct
  383. pcs_changed = pcs && pl->pcs != pcs;
  384. }
  385. + phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising);
  386. +
  387. + phylink_dbg(pl, "major config, active %s/%s/%s\n",
  388. + phylink_an_mode_str(pl->act_link_an_mode),
  389. + phylink_pcs_mode_str(pl->pcs_neg_mode),
  390. + phy_modes(state->interface));
  391. +
  392. phylink_pcs_poll_stop(pl);
  393. if (pl->mac_ops->mac_prepare) {
  394. - err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode,
  395. + err = pl->mac_ops->mac_prepare(pl->config, pl->act_link_an_mode,
  396. state->interface);
  397. if (err < 0) {
  398. phylink_err(pl, "mac_prepare failed: %pe\n",
  399. @@ -1280,7 +1462,7 @@ static void phylink_major_config(struct
  400. if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed)
  401. phylink_pcs_enable(pl->pcs);
  402. - neg_mode = pl->cur_link_an_mode;
  403. + neg_mode = pl->act_link_an_mode;
  404. if (pl->pcs && pl->pcs->neg_mode)
  405. neg_mode = pl->pcs_neg_mode;
  406. @@ -1296,13 +1478,20 @@ static void phylink_major_config(struct
  407. phylink_pcs_an_restart(pl);
  408. if (pl->mac_ops->mac_finish) {
  409. - err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode,
  410. + err = pl->mac_ops->mac_finish(pl->config, pl->act_link_an_mode,
  411. state->interface);
  412. if (err < 0)
  413. phylink_err(pl, "mac_finish failed: %pe\n",
  414. ERR_PTR(err));
  415. }
  416. + if (pl->phydev && pl->phy_ib_mode) {
  417. + err = phy_config_inband(pl->phydev, pl->phy_ib_mode);
  418. + if (err < 0)
  419. + phylink_err(pl, "phy_config_inband: %pe\n",
  420. + ERR_PTR(err));
  421. + }
  422. +
  423. if (pl->sfp_bus) {
  424. rate_kbd = phylink_interface_signal_rate(state->interface);
  425. if (rate_kbd)
  426. @@ -1327,17 +1516,16 @@ static int phylink_change_inband_advert(
  427. return 0;
  428. phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__,
  429. - phylink_an_mode_str(pl->cur_link_an_mode),
  430. + phylink_an_mode_str(pl->req_link_an_mode),
  431. phy_modes(pl->link_config.interface),
  432. __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
  433. pl->link_config.pause);
  434. /* Recompute the PCS neg mode */
  435. - pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
  436. - pl->link_config.interface,
  437. - pl->link_config.advertising);
  438. + phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface,
  439. + pl->link_config.advertising);
  440. - neg_mode = pl->cur_link_an_mode;
  441. + neg_mode = pl->act_link_an_mode;
  442. if (pl->pcs->neg_mode)
  443. neg_mode = pl->pcs_neg_mode;
  444. @@ -1402,7 +1590,7 @@ static void phylink_mac_initial_config(s
  445. {
  446. struct phylink_link_state link_state;
  447. - switch (pl->cur_link_an_mode) {
  448. + switch (pl->req_link_an_mode) {
  449. case MLO_AN_PHY:
  450. link_state = pl->phy_state;
  451. break;
  452. @@ -1476,14 +1664,14 @@ static void phylink_link_up(struct phyli
  453. pl->cur_interface = link_state.interface;
  454. - neg_mode = pl->cur_link_an_mode;
  455. + neg_mode = pl->act_link_an_mode;
  456. if (pl->pcs && pl->pcs->neg_mode)
  457. neg_mode = pl->pcs_neg_mode;
  458. phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed,
  459. duplex);
  460. - pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode,
  461. + pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->act_link_an_mode,
  462. pl->cur_interface, speed, duplex,
  463. !!(link_state.pause & MLO_PAUSE_TX), rx_pause);
  464. @@ -1503,7 +1691,7 @@ static void phylink_link_down(struct phy
  465. if (ndev)
  466. netif_carrier_off(ndev);
  467. - pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode,
  468. + pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode,
  469. pl->cur_interface);
  470. phylink_info(pl, "Link is Down\n");
  471. }
  472. @@ -1530,7 +1718,7 @@ static void phylink_resolve(struct work_
  473. link_state.link = false;
  474. retrigger = true;
  475. } else {
  476. - switch (pl->cur_link_an_mode) {
  477. + switch (pl->act_link_an_mode) {
  478. case MLO_AN_PHY:
  479. link_state = pl->phy_state;
  480. phylink_apply_manual_flow(pl, &link_state);
  481. @@ -1773,7 +1961,7 @@ struct phylink *phylink_create(struct ph
  482. }
  483. }
  484. - pl->cur_link_an_mode = pl->cfg_link_an_mode;
  485. + pl->req_link_an_mode = pl->cfg_link_an_mode;
  486. ret = phylink_register_sfp(pl, fwnode);
  487. if (ret < 0) {
  488. @@ -2236,7 +2424,7 @@ void phylink_start(struct phylink *pl)
  489. ASSERT_RTNL();
  490. phylink_info(pl, "configuring for %s/%s link mode\n",
  491. - phylink_an_mode_str(pl->cur_link_an_mode),
  492. + phylink_an_mode_str(pl->req_link_an_mode),
  493. phy_modes(pl->link_config.interface));
  494. /* Always set the carrier off */
  495. @@ -2495,7 +2683,7 @@ int phylink_ethtool_ksettings_get(struct
  496. linkmode_copy(kset->link_modes.supported, pl->supported);
  497. - switch (pl->cur_link_an_mode) {
  498. + switch (pl->act_link_an_mode) {
  499. case MLO_AN_FIXED:
  500. /* We are using fixed settings. Report these as the
  501. * current link settings - and note that these also
  502. @@ -2526,6 +2714,26 @@ int phylink_ethtool_ksettings_get(struct
  503. }
  504. EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get);
  505. +static bool phylink_validate_pcs_inband_autoneg(struct phylink *pl,
  506. + phy_interface_t interface,
  507. + unsigned long *adv)
  508. +{
  509. + unsigned int inband = phylink_inband_caps(pl, interface);
  510. + unsigned int mask;
  511. +
  512. + /* If the PCS doesn't implement inband support, be permissive. */
  513. + if (!inband)
  514. + return true;
  515. +
  516. + if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv))
  517. + mask = LINK_INBAND_ENABLE;
  518. + else
  519. + mask = LINK_INBAND_DISABLE;
  520. +
  521. + /* Check whether the PCS implements the required mode */
  522. + return !!(inband & mask);
  523. +}
  524. +
  525. /**
  526. * phylink_ethtool_ksettings_set() - set the link settings
  527. * @pl: a pointer to a &struct phylink returned from phylink_create()
  528. @@ -2587,7 +2795,7 @@ int phylink_ethtool_ksettings_set(struct
  529. /* If we have a fixed link, refuse to change link parameters.
  530. * If the link parameters match, accept them but do nothing.
  531. */
  532. - if (pl->cur_link_an_mode == MLO_AN_FIXED) {
  533. + if (pl->req_link_an_mode == MLO_AN_FIXED) {
  534. if (s->speed != pl->link_config.speed ||
  535. s->duplex != pl->link_config.duplex)
  536. return -EINVAL;
  537. @@ -2603,7 +2811,7 @@ int phylink_ethtool_ksettings_set(struct
  538. * is our default case) but do not allow the advertisement to
  539. * be changed. If the advertisement matches, simply return.
  540. */
  541. - if (pl->cur_link_an_mode == MLO_AN_FIXED) {
  542. + if (pl->req_link_an_mode == MLO_AN_FIXED) {
  543. if (!linkmode_equal(config.advertising,
  544. pl->link_config.advertising))
  545. return -EINVAL;
  546. @@ -2643,7 +2851,7 @@ int phylink_ethtool_ksettings_set(struct
  547. linkmode_copy(support, pl->supported);
  548. if (phylink_validate(pl, support, &config)) {
  549. phylink_err(pl, "validation of %s/%s with support %*pb failed\n",
  550. - phylink_an_mode_str(pl->cur_link_an_mode),
  551. + phylink_an_mode_str(pl->req_link_an_mode),
  552. phy_modes(config.interface),
  553. __ETHTOOL_LINK_MODE_MASK_NBITS, support);
  554. return -EINVAL;
  555. @@ -2661,6 +2869,13 @@ int phylink_ethtool_ksettings_set(struct
  556. phylink_is_empty_linkmode(config.advertising))
  557. return -EINVAL;
  558. + /* Validate the autonegotiation state. We don't have a PHY in this
  559. + * situation, so the PCS is the media-facing entity.
  560. + */
  561. + if (!phylink_validate_pcs_inband_autoneg(pl, config.interface,
  562. + config.advertising))
  563. + return -EINVAL;
  564. +
  565. mutex_lock(&pl->state_mutex);
  566. pl->link_config.speed = config.speed;
  567. pl->link_config.duplex = config.duplex;
  568. @@ -2743,7 +2958,7 @@ int phylink_ethtool_set_pauseparam(struc
  569. ASSERT_RTNL();
  570. - if (pl->cur_link_an_mode == MLO_AN_FIXED)
  571. + if (pl->req_link_an_mode == MLO_AN_FIXED)
  572. return -EOPNOTSUPP;
  573. if (!phylink_test(pl->supported, Pause) &&
  574. @@ -3007,7 +3222,7 @@ static int phylink_mii_read(struct phyli
  575. struct phylink_link_state state;
  576. int val = 0xffff;
  577. - switch (pl->cur_link_an_mode) {
  578. + switch (pl->act_link_an_mode) {
  579. case MLO_AN_FIXED:
  580. if (phy_id == 0) {
  581. phylink_get_fixed_state(pl, &state);
  582. @@ -3032,7 +3247,7 @@ static int phylink_mii_read(struct phyli
  583. static int phylink_mii_write(struct phylink *pl, unsigned int phy_id,
  584. unsigned int reg, unsigned int val)
  585. {
  586. - switch (pl->cur_link_an_mode) {
  587. + switch (pl->act_link_an_mode) {
  588. case MLO_AN_FIXED:
  589. break;
  590. @@ -3202,10 +3417,11 @@ static phy_interface_t phylink_choose_sf
  591. return interface;
  592. }
  593. -static void phylink_sfp_set_config(struct phylink *pl, u8 mode,
  594. +static void phylink_sfp_set_config(struct phylink *pl,
  595. unsigned long *supported,
  596. struct phylink_link_state *state)
  597. {
  598. + u8 mode = MLO_AN_INBAND;
  599. bool changed = false;
  600. phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
  601. @@ -3222,9 +3438,9 @@ static void phylink_sfp_set_config(struc
  602. changed = true;
  603. }
  604. - if (pl->cur_link_an_mode != mode ||
  605. + if (pl->req_link_an_mode != mode ||
  606. pl->link_config.interface != state->interface) {
  607. - pl->cur_link_an_mode = mode;
  608. + pl->req_link_an_mode = mode;
  609. pl->link_config.interface = state->interface;
  610. changed = true;
  611. @@ -3239,8 +3455,7 @@ static void phylink_sfp_set_config(struc
  612. phylink_mac_initial_config(pl, false);
  613. }
  614. -static int phylink_sfp_config_phy(struct phylink *pl, u8 mode,
  615. - struct phy_device *phy)
  616. +static int phylink_sfp_config_phy(struct phylink *pl, struct phy_device *phy)
  617. {
  618. __ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
  619. __ETHTOOL_DECLARE_LINK_MODE_MASK(support);
  620. @@ -3279,8 +3494,7 @@ static int phylink_sfp_config_phy(struct
  621. ret = phylink_validate(pl, support1, &config);
  622. if (ret) {
  623. phylink_err(pl,
  624. - "validation of %s/%s with support %*pb failed: %pe\n",
  625. - phylink_an_mode_str(mode),
  626. + "validation of %s with support %*pb failed: %pe\n",
  627. phy_modes(config.interface),
  628. __ETHTOOL_LINK_MODE_MASK_NBITS, support,
  629. ERR_PTR(ret));
  630. @@ -3289,7 +3503,7 @@ static int phylink_sfp_config_phy(struct
  631. pl->link_port = pl->sfp_port;
  632. - phylink_sfp_set_config(pl, mode, support, &config);
  633. + phylink_sfp_set_config(pl, support, &config);
  634. return 0;
  635. }
  636. @@ -3345,6 +3559,12 @@ static int phylink_sfp_config_optical(st
  637. phylink_dbg(pl, "optical SFP: chosen %s interface\n",
  638. phy_modes(interface));
  639. + if (!phylink_validate_pcs_inband_autoneg(pl, interface,
  640. + config.advertising)) {
  641. + phylink_err(pl, "autoneg setting not compatible with PCS");
  642. + return -EINVAL;
  643. + }
  644. +
  645. config.interface = interface;
  646. /* Ignore errors if we're expecting a PHY to attach later */
  647. @@ -3358,7 +3578,7 @@ static int phylink_sfp_config_optical(st
  648. pl->link_port = pl->sfp_port;
  649. - phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config);
  650. + phylink_sfp_set_config(pl, pl->sfp_support, &config);
  651. return 0;
  652. }
  653. @@ -3429,20 +3649,10 @@ static void phylink_sfp_link_up(void *up
  654. phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK);
  655. }
  656. -/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
  657. - * or 802.3z control word, so inband will not work.
  658. - */
  659. -static bool phylink_phy_no_inband(struct phy_device *phy)
  660. -{
  661. - return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1],
  662. - 0xae025150, 0xfffffff0);
  663. -}
  664. -
  665. static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
  666. {
  667. struct phylink *pl = upstream;
  668. phy_interface_t interface;
  669. - u8 mode;
  670. int ret;
  671. /*
  672. @@ -3454,17 +3664,12 @@ static int phylink_sfp_connect_phy(void
  673. */
  674. phy_support_asym_pause(phy);
  675. - if (phylink_phy_no_inband(phy))
  676. - mode = MLO_AN_PHY;
  677. - else
  678. - mode = MLO_AN_INBAND;
  679. -
  680. /* Set the PHY's host supported interfaces */
  681. phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces,
  682. pl->config->supported_interfaces);
  683. /* Do the initial configuration */
  684. - ret = phylink_sfp_config_phy(pl, mode, phy);
  685. + ret = phylink_sfp_config_phy(pl, phy);
  686. if (ret < 0)
  687. return ret;
  688. --- a/drivers/net/phy/phy.c
  689. +++ b/drivers/net/phy/phy.c
  690. @@ -973,6 +973,58 @@ static int phy_check_link_status(struct
  691. }
  692. /**
  693. + * phy_inband_caps - query which in-band signalling modes are supported
  694. + * @phydev: a pointer to a &struct phy_device
  695. + * @interface: the interface mode for the PHY
  696. + *
  697. + * Returns zero if it is unknown what in-band signalling is supported by the
  698. + * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
  699. + * returns a bit mask of the LINK_INBAND_* values from
  700. + * &enum link_inband_signalling to describe which inband modes are supported
  701. + * by the PHY for this interface mode.
  702. + */
  703. +unsigned int phy_inband_caps(struct phy_device *phydev,
  704. + phy_interface_t interface)
  705. +{
  706. + if (phydev->drv && phydev->drv->inband_caps)
  707. + return phydev->drv->inband_caps(phydev, interface);
  708. +
  709. + return 0;
  710. +}
  711. +EXPORT_SYMBOL_GPL(phy_inband_caps);
  712. +
  713. +/**
  714. + * phy_config_inband - configure the desired PHY in-band mode
  715. + * @phydev: the phy_device struct
  716. + * @modes: in-band modes to configure
  717. + *
  718. + * Description: disables, enables or enables-with-bypass in-band signalling
  719. + * between the PHY and host system.
  720. + *
  721. + * Returns: zero on success, or negative errno value.
  722. + */
  723. +int phy_config_inband(struct phy_device *phydev, unsigned int modes)
  724. +{
  725. + int err;
  726. +
  727. + if (!!(modes & LINK_INBAND_DISABLE) +
  728. + !!(modes & LINK_INBAND_ENABLE) +
  729. + !!(modes & LINK_INBAND_BYPASS) != 1)
  730. + return -EINVAL;
  731. +
  732. + mutex_lock(&phydev->lock);
  733. + if (!phydev->drv)
  734. + err = -EIO;
  735. + else if (!phydev->drv->config_inband)
  736. + err = -EOPNOTSUPP;
  737. + else
  738. + err = phydev->drv->config_inband(phydev, modes);
  739. + mutex_unlock(&phydev->lock);
  740. +
  741. + return err;
  742. +}
  743. +
  744. +/**
  745. * _phy_start_aneg - start auto-negotiation for this PHY device
  746. * @phydev: the phy_device struct
  747. *
  748. --- a/include/linux/phy.h
  749. +++ b/include/linux/phy.h
  750. @@ -800,6 +800,24 @@ struct phy_tdr_config {
  751. #define PHY_PAIR_ALL -1
  752. /**
  753. + * enum link_inband_signalling - in-band signalling modes that are supported
  754. + *
  755. + * @LINK_INBAND_DISABLE: in-band signalling can be disabled
  756. + * @LINK_INBAND_ENABLE: in-band signalling can be enabled without bypass
  757. + * @LINK_INBAND_BYPASS: in-band signalling can be enabled with bypass
  758. + *
  759. + * The possible and required bits can only be used if the valid bit is set.
  760. + * If possible is clear, that means inband signalling can not be used.
  761. + * Required is only valid when possible is set, and means that inband
  762. + * signalling must be used.
  763. + */
  764. +enum link_inband_signalling {
  765. + LINK_INBAND_DISABLE = BIT(0),
  766. + LINK_INBAND_ENABLE = BIT(1),
  767. + LINK_INBAND_BYPASS = BIT(2),
  768. +};
  769. +
  770. +/**
  771. * struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collision
  772. * Avoidance) Reconciliation Sublayer.
  773. *
  774. @@ -939,6 +957,19 @@ struct phy_driver {
  775. int (*get_features)(struct phy_device *phydev);
  776. /**
  777. + * @inband_caps: query whether in-band is supported for the given PHY
  778. + * interface mode. Returns a bitmask of bits defined by enum
  779. + * link_inband_signalling.
  780. + */
  781. + unsigned int (*inband_caps)(struct phy_device *phydev,
  782. + phy_interface_t interface);
  783. +
  784. + /**
  785. + * @config_inband: configure in-band mode for the PHY
  786. + */
  787. + int (*config_inband)(struct phy_device *phydev, unsigned int modes);
  788. +
  789. + /**
  790. * @get_rate_matching: Get the supported type of rate matching for a
  791. * particular phy interface. This is used by phy consumers to determine
  792. * whether to advertise lower-speed modes for that interface. It is
  793. @@ -1774,6 +1805,9 @@ void phy_stop(struct phy_device *phydev)
  794. int phy_config_aneg(struct phy_device *phydev);
  795. int phy_start_aneg(struct phy_device *phydev);
  796. int phy_aneg_done(struct phy_device *phydev);
  797. +unsigned int phy_inband_caps(struct phy_device *phydev,
  798. + phy_interface_t interface);
  799. +int phy_config_inband(struct phy_device *phydev, unsigned int modes);
  800. int phy_speed_down(struct phy_device *phydev, bool sync);
  801. int phy_speed_up(struct phy_device *phydev);
  802. bool phy_check_valid(int speed, int duplex, unsigned long *features);
  803. --- a/drivers/net/phy/bcm84881.c
  804. +++ b/drivers/net/phy/bcm84881.c
  805. @@ -223,11 +223,21 @@ static int bcm84881_read_status(struct p
  806. return genphy_c45_read_mdix(phydev);
  807. }
  808. +/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
  809. + * or 802.3z control word, so inband will not work.
  810. + */
  811. +static unsigned int bcm84881_inband_caps(struct phy_device *phydev,
  812. + phy_interface_t interface)
  813. +{
  814. + return LINK_INBAND_DISABLE;
  815. +}
  816. +
  817. static struct phy_driver bcm84881_drivers[] = {
  818. {
  819. .phy_id = 0xae025150,
  820. .phy_id_mask = 0xfffffff0,
  821. .name = "Broadcom BCM84881",
  822. + .inband_caps = bcm84881_inband_caps,
  823. .config_init = bcm84881_config_init,
  824. .probe = bcm84881_probe,
  825. .get_features = bcm84881_get_features,
  826. --- a/drivers/net/phy/marvell.c
  827. +++ b/drivers/net/phy/marvell.c
  828. @@ -673,6 +673,48 @@ static int marvell_config_aneg_fiber(str
  829. return genphy_check_and_restart_aneg(phydev, changed);
  830. }
  831. +static unsigned int m88e1111_inband_caps(struct phy_device *phydev,
  832. + phy_interface_t interface)
  833. +{
  834. + /* In 1000base-X and SGMII modes, the inband mode can be changed
  835. + * through the Fibre page BMCR ANENABLE bit.
  836. + */
  837. + if (interface == PHY_INTERFACE_MODE_1000BASEX ||
  838. + interface == PHY_INTERFACE_MODE_SGMII)
  839. + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE |
  840. + LINK_INBAND_BYPASS;
  841. +
  842. + return 0;
  843. +}
  844. +
  845. +static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes)
  846. +{
  847. + u16 extsr, bmcr;
  848. + int err;
  849. +
  850. + if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX &&
  851. + phydev->interface != PHY_INTERFACE_MODE_SGMII)
  852. + return -EINVAL;
  853. +
  854. + if (modes == LINK_INBAND_BYPASS)
  855. + extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS;
  856. + else
  857. + extsr = 0;
  858. +
  859. + if (modes == LINK_INBAND_DISABLE)
  860. + bmcr = 0;
  861. + else
  862. + bmcr = BMCR_ANENABLE;
  863. +
  864. + err = phy_modify(phydev, MII_M1111_PHY_EXT_SR,
  865. + MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr);
  866. + if (err < 0)
  867. + return extsr;
  868. +
  869. + return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR,
  870. + BMCR_ANENABLE, bmcr);
  871. +}
  872. +
  873. static int m88e1111_config_aneg(struct phy_device *phydev)
  874. {
  875. int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
  876. @@ -3292,6 +3334,8 @@ static struct phy_driver marvell_drivers
  877. .name = "Marvell 88E1112",
  878. /* PHY_GBIT_FEATURES */
  879. .probe = marvell_probe,
  880. + .inband_caps = m88e1111_inband_caps,
  881. + .config_inband = m88e1111_config_inband,
  882. .config_init = m88e1112_config_init,
  883. .config_aneg = marvell_config_aneg,
  884. .config_intr = marvell_config_intr,
  885. @@ -3312,6 +3356,8 @@ static struct phy_driver marvell_drivers
  886. .name = "Marvell 88E1111",
  887. /* PHY_GBIT_FEATURES */
  888. .probe = marvell_probe,
  889. + .inband_caps = m88e1111_inband_caps,
  890. + .config_inband = m88e1111_config_inband,
  891. .config_init = m88e1111gbe_config_init,
  892. .config_aneg = m88e1111_config_aneg,
  893. .read_status = marvell_read_status,
  894. @@ -3333,6 +3379,8 @@ static struct phy_driver marvell_drivers
  895. .name = "Marvell 88E1111 (Finisar)",
  896. /* PHY_GBIT_FEATURES */
  897. .probe = marvell_probe,
  898. + .inband_caps = m88e1111_inband_caps,
  899. + .config_inband = m88e1111_config_inband,
  900. .config_init = m88e1111gbe_config_init,
  901. .config_aneg = m88e1111_config_aneg,
  902. .read_status = marvell_read_status,
  903. --- a/include/linux/phylink.h
  904. +++ b/include/linux/phylink.h
  905. @@ -432,6 +432,7 @@ struct phylink_pcs {
  906. /**
  907. * struct phylink_pcs_ops - MAC PCS operations structure.
  908. * @pcs_validate: validate the link configuration.
  909. + * @pcs_inband_caps: query inband support for interface mode.
  910. * @pcs_enable: enable the PCS.
  911. * @pcs_disable: disable the PCS.
  912. * @pcs_pre_config: pre-mac_config method (for errata)
  913. @@ -445,6 +446,8 @@ struct phylink_pcs {
  914. struct phylink_pcs_ops {
  915. int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
  916. const struct phylink_link_state *state);
  917. + unsigned int (*pcs_inband_caps)(struct phylink_pcs *pcs,
  918. + phy_interface_t interface);
  919. int (*pcs_enable)(struct phylink_pcs *pcs);
  920. void (*pcs_disable)(struct phylink_pcs *pcs);
  921. void (*pcs_pre_config)(struct phylink_pcs *pcs,
  922. @@ -481,6 +484,20 @@ int pcs_validate(struct phylink_pcs *pcs
  923. const struct phylink_link_state *state);
  924. /**
  925. + * pcs_inband_caps - query PCS in-band capabilities for interface mode.
  926. + * @pcs: a pointer to a &struct phylink_pcs.
  927. + * @interface: interface mode to be queried
  928. + *
  929. + * Returns zero if it is unknown what in-band signalling is supported by the
  930. + * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
  931. + * returns a bit mask of the LINK_INBAND_* values from
  932. + * &enum link_inband_signalling to describe which inband modes are supported
  933. + * for this interface mode.
  934. + */
  935. +unsigned int pcs_inband_caps(struct phylink_pcs *pcs,
  936. + phy_interface_t interface);
  937. +
  938. +/**
  939. * pcs_enable() - enable the PCS.
  940. * @pcs: a pointer to a &struct phylink_pcs.
  941. */
  942. --- a/drivers/net/ethernet/marvell/mvneta.c
  943. +++ b/drivers/net/ethernet/marvell/mvneta.c
  944. @@ -3959,20 +3959,27 @@ static struct mvneta_port *mvneta_pcs_to
  945. return container_of(pcs, struct mvneta_port, phylink_pcs);
  946. }
  947. -static int mvneta_pcs_validate(struct phylink_pcs *pcs,
  948. - unsigned long *supported,
  949. - const struct phylink_link_state *state)
  950. +static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs,
  951. + phy_interface_t interface)
  952. {
  953. - /* We only support QSGMII, SGMII, 802.3z and RGMII modes.
  954. - * When in 802.3z mode, we must have AN enabled:
  955. + /* When operating in an 802.3z mode, we must have AN enabled:
  956. * "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
  957. * When <PortType> = 1 (1000BASE-X) this field must be set to 1."
  958. + * Therefore, inband is "required".
  959. */
  960. - if (phy_interface_mode_is_8023z(state->interface) &&
  961. - !phylink_test(state->advertising, Autoneg))
  962. - return -EINVAL;
  963. + if (phy_interface_mode_is_8023z(interface))
  964. + return LINK_INBAND_ENABLE;
  965. - return 0;
  966. + /* QSGMII, SGMII and RGMII can be configured to use inband
  967. + * signalling of the AN result. Indicate these as "possible".
  968. + */
  969. + if (interface == PHY_INTERFACE_MODE_SGMII ||
  970. + interface == PHY_INTERFACE_MODE_QSGMII ||
  971. + phy_interface_mode_is_rgmii(interface))
  972. + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
  973. +
  974. + /* For any other modes, indicate that inband is not supported. */
  975. + return LINK_INBAND_DISABLE;
  976. }
  977. static void mvneta_pcs_get_state(struct phylink_pcs *pcs,
  978. @@ -4070,7 +4077,7 @@ static void mvneta_pcs_an_restart(struct
  979. }
  980. static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = {
  981. - .pcs_validate = mvneta_pcs_validate,
  982. + .pcs_inband_caps = mvneta_pcs_inband_caps,
  983. .pcs_get_state = mvneta_pcs_get_state,
  984. .pcs_config = mvneta_pcs_config,
  985. .pcs_an_restart = mvneta_pcs_an_restart,
  986. --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
  987. +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
  988. @@ -6214,19 +6214,26 @@ static const struct phylink_pcs_ops mvpp
  989. .pcs_config = mvpp2_xlg_pcs_config,
  990. };
  991. -static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs,
  992. - unsigned long *supported,
  993. - const struct phylink_link_state *state)
  994. +static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs,
  995. + phy_interface_t interface)
  996. {
  997. - /* When in 802.3z mode, we must have AN enabled:
  998. + /* When operating in an 802.3z mode, we must have AN enabled:
  999. * Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
  1000. * When <PortType> = 1 (1000BASE-X) this field must be set to 1.
  1001. + * Therefore, inband is "required".
  1002. */
  1003. - if (phy_interface_mode_is_8023z(state->interface) &&
  1004. - !phylink_test(state->advertising, Autoneg))
  1005. - return -EINVAL;
  1006. + if (phy_interface_mode_is_8023z(interface))
  1007. + return LINK_INBAND_ENABLE;
  1008. - return 0;
  1009. + /* SGMII and RGMII can be configured to use inband signalling of the
  1010. + * AN result. Indicate these as "possible".
  1011. + */
  1012. + if (interface == PHY_INTERFACE_MODE_SGMII ||
  1013. + phy_interface_mode_is_rgmii(interface))
  1014. + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
  1015. +
  1016. + /* For any other modes, indicate that inband is not supported. */
  1017. + return LINK_INBAND_DISABLE;
  1018. }
  1019. static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs,
  1020. @@ -6333,7 +6340,7 @@ static void mvpp2_gmac_pcs_an_restart(st
  1021. }
  1022. static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = {
  1023. - .pcs_validate = mvpp2_gmac_pcs_validate,
  1024. + .pcs_inband_caps = mvpp2_gmac_pcs_inband_caps,
  1025. .pcs_get_state = mvpp2_gmac_pcs_get_state,
  1026. .pcs_config = mvpp2_gmac_pcs_config,
  1027. .pcs_an_restart = mvpp2_gmac_pcs_an_restart,
  1028. --- a/drivers/net/pcs/pcs-lynx.c
  1029. +++ b/drivers/net/pcs/pcs-lynx.c
  1030. @@ -35,6 +35,27 @@ enum sgmii_speed {
  1031. #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
  1032. #define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)
  1033. +static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs,
  1034. + phy_interface_t interface)
  1035. +{
  1036. + switch (interface) {
  1037. + case PHY_INTERFACE_MODE_1000BASEX:
  1038. + case PHY_INTERFACE_MODE_SGMII:
  1039. + case PHY_INTERFACE_MODE_QSGMII:
  1040. + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
  1041. +
  1042. + case PHY_INTERFACE_MODE_10GBASER:
  1043. + case PHY_INTERFACE_MODE_2500BASEX:
  1044. + return LINK_INBAND_DISABLE;
  1045. +
  1046. + case PHY_INTERFACE_MODE_USXGMII:
  1047. + return LINK_INBAND_ENABLE;
  1048. +
  1049. + default:
  1050. + return 0;
  1051. + }
  1052. +}
  1053. +
  1054. static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
  1055. struct phylink_link_state *state)
  1056. {
  1057. @@ -307,6 +328,7 @@ static void lynx_pcs_link_up(struct phyl
  1058. }
  1059. static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
  1060. + .pcs_inband_caps = lynx_pcs_inband_caps,
  1061. .pcs_get_state = lynx_pcs_get_state,
  1062. .pcs_config = lynx_pcs_config,
  1063. .pcs_an_restart = lynx_pcs_an_restart,
  1064. --- a/drivers/net/pcs/pcs-mtk-lynxi.c
  1065. +++ b/drivers/net/pcs/pcs-mtk-lynxi.c
  1066. @@ -110,6 +110,21 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_
  1067. return container_of(pcs, struct mtk_pcs_lynxi, pcs);
  1068. }
  1069. +static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs,
  1070. + phy_interface_t interface)
  1071. +{
  1072. + switch (interface) {
  1073. + case PHY_INTERFACE_MODE_1000BASEX:
  1074. + case PHY_INTERFACE_MODE_2500BASEX:
  1075. + case PHY_INTERFACE_MODE_SGMII:
  1076. + case PHY_INTERFACE_MODE_QSGMII:
  1077. + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
  1078. +
  1079. + default:
  1080. + return 0;
  1081. + }
  1082. +}
  1083. +
  1084. static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
  1085. struct phylink_link_state *state)
  1086. {
  1087. @@ -302,6 +317,7 @@ static void mtk_pcs_lynxi_disable(struct
  1088. }
  1089. static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = {
  1090. + .pcs_inband_caps = mtk_pcs_lynxi_inband_caps,
  1091. .pcs_get_state = mtk_pcs_lynxi_get_state,
  1092. .pcs_config = mtk_pcs_lynxi_config,
  1093. .pcs_an_restart = mtk_pcs_lynxi_restart_an,
  1094. --- a/drivers/net/pcs/pcs-xpcs.c
  1095. +++ b/drivers/net/pcs/pcs-xpcs.c
  1096. @@ -628,6 +628,33 @@ static int xpcs_validate(struct phylink_
  1097. return 0;
  1098. }
  1099. +static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs,
  1100. + phy_interface_t interface)
  1101. +{
  1102. + struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
  1103. + const struct dw_xpcs_compat *compat;
  1104. +
  1105. + compat = xpcs_find_compat(xpcs, interface);
  1106. + if (!compat)
  1107. + return 0;
  1108. +
  1109. + switch (compat->an_mode) {
  1110. + case DW_AN_C73:
  1111. + return LINK_INBAND_ENABLE;
  1112. +
  1113. + case DW_AN_C37_SGMII:
  1114. + case DW_AN_C37_1000BASEX:
  1115. + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
  1116. +
  1117. + case DW_10GBASER:
  1118. + case DW_2500BASEX:
  1119. + return LINK_INBAND_DISABLE;
  1120. +
  1121. + default:
  1122. + return 0;
  1123. + }
  1124. +}
  1125. +
  1126. void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
  1127. {
  1128. int i, j;
  1129. @@ -1331,6 +1358,7 @@ static const struct xpcs_id xpcs_id_list
  1130. static const struct phylink_pcs_ops xpcs_phylink_ops = {
  1131. .pcs_validate = xpcs_validate,
  1132. + .pcs_inband_caps = xpcs_inband_caps,
  1133. .pcs_config = xpcs_config,
  1134. .pcs_get_state = xpcs_get_state,
  1135. .pcs_an_restart = xpcs_an_restart,