mcdi_port.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  1. /****************************************************************************
  2. * Driver for Solarflare network controllers and boards
  3. * Copyright 2009-2013 Solarflare Communications Inc.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 as published
  7. * by the Free Software Foundation, incorporated herein by reference.
  8. */
  9. /*
  10. * Driver for PHY related operations via MCDI.
  11. */
  12. #include <linux/slab.h>
  13. #include "efx.h"
  14. #include "mcdi.h"
  15. #include "mcdi_pcol.h"
  16. #include "nic.h"
  17. #include "selftest.h"
  18. struct efx_mcdi_phy_data {
  19. u32 flags;
  20. u32 type;
  21. u32 supported_cap;
  22. u32 channel;
  23. u32 port;
  24. u32 stats_mask;
  25. u8 name[20];
  26. u32 media;
  27. u32 mmd_mask;
  28. u8 revision[20];
  29. u32 forced_cap;
  30. };
  31. static int
  32. efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_data *cfg)
  33. {
  34. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_CFG_OUT_LEN);
  35. size_t outlen;
  36. int rc;
  37. BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_IN_LEN != 0);
  38. BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_OUT_NAME_LEN != sizeof(cfg->name));
  39. rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_CFG, NULL, 0,
  40. outbuf, sizeof(outbuf), &outlen);
  41. if (rc)
  42. goto fail;
  43. if (outlen < MC_CMD_GET_PHY_CFG_OUT_LEN) {
  44. rc = -EIO;
  45. goto fail;
  46. }
  47. cfg->flags = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_FLAGS);
  48. cfg->type = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_TYPE);
  49. cfg->supported_cap =
  50. MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_SUPPORTED_CAP);
  51. cfg->channel = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_CHANNEL);
  52. cfg->port = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_PRT);
  53. cfg->stats_mask = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_STATS_MASK);
  54. memcpy(cfg->name, MCDI_PTR(outbuf, GET_PHY_CFG_OUT_NAME),
  55. sizeof(cfg->name));
  56. cfg->media = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_MEDIA_TYPE);
  57. cfg->mmd_mask = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_MMD_MASK);
  58. memcpy(cfg->revision, MCDI_PTR(outbuf, GET_PHY_CFG_OUT_REVISION),
  59. sizeof(cfg->revision));
  60. return 0;
  61. fail:
  62. netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
  63. return rc;
  64. }
  65. static int efx_mcdi_set_link(struct efx_nic *efx, u32 capabilities,
  66. u32 flags, u32 loopback_mode,
  67. u32 loopback_speed)
  68. {
  69. MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_LINK_IN_LEN);
  70. int rc;
  71. BUILD_BUG_ON(MC_CMD_SET_LINK_OUT_LEN != 0);
  72. MCDI_SET_DWORD(inbuf, SET_LINK_IN_CAP, capabilities);
  73. MCDI_SET_DWORD(inbuf, SET_LINK_IN_FLAGS, flags);
  74. MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_MODE, loopback_mode);
  75. MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_SPEED, loopback_speed);
  76. rc = efx_mcdi_rpc(efx, MC_CMD_SET_LINK, inbuf, sizeof(inbuf),
  77. NULL, 0, NULL);
  78. return rc;
  79. }
  80. static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes)
  81. {
  82. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LOOPBACK_MODES_OUT_LEN);
  83. size_t outlen;
  84. int rc;
  85. rc = efx_mcdi_rpc(efx, MC_CMD_GET_LOOPBACK_MODES, NULL, 0,
  86. outbuf, sizeof(outbuf), &outlen);
  87. if (rc)
  88. goto fail;
  89. if (outlen < (MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
  90. MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN)) {
  91. rc = -EIO;
  92. goto fail;
  93. }
  94. *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_OUT_SUGGESTED);
  95. return 0;
  96. fail:
  97. netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
  98. return rc;
  99. }
  100. static int efx_mcdi_mdio_read(struct net_device *net_dev,
  101. int prtad, int devad, u16 addr)
  102. {
  103. struct efx_nic *efx = netdev_priv(net_dev);
  104. MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN);
  105. MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN);
  106. size_t outlen;
  107. int rc;
  108. MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, efx->mdio_bus);
  109. MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad);
  110. MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad);
  111. MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr);
  112. rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf),
  113. outbuf, sizeof(outbuf), &outlen);
  114. if (rc)
  115. return rc;
  116. if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) !=
  117. MC_CMD_MDIO_STATUS_GOOD)
  118. return -EIO;
  119. return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE);
  120. }
  121. static int efx_mcdi_mdio_write(struct net_device *net_dev,
  122. int prtad, int devad, u16 addr, u16 value)
  123. {
  124. struct efx_nic *efx = netdev_priv(net_dev);
  125. MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN);
  126. MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN);
  127. size_t outlen;
  128. int rc;
  129. MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus);
  130. MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad);
  131. MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad);
  132. MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr);
  133. MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value);
  134. rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf),
  135. outbuf, sizeof(outbuf), &outlen);
  136. if (rc)
  137. return rc;
  138. if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) !=
  139. MC_CMD_MDIO_STATUS_GOOD)
  140. return -EIO;
  141. return 0;
  142. }
  143. static u32 mcdi_to_ethtool_cap(u32 media, u32 cap)
  144. {
  145. u32 result = 0;
  146. switch (media) {
  147. case MC_CMD_MEDIA_KX4:
  148. result |= SUPPORTED_Backplane;
  149. if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
  150. result |= SUPPORTED_1000baseKX_Full;
  151. if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
  152. result |= SUPPORTED_10000baseKX4_Full;
  153. if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
  154. result |= SUPPORTED_40000baseKR4_Full;
  155. break;
  156. case MC_CMD_MEDIA_XFP:
  157. case MC_CMD_MEDIA_SFP_PLUS:
  158. case MC_CMD_MEDIA_QSFP_PLUS:
  159. result |= SUPPORTED_FIBRE;
  160. if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
  161. result |= SUPPORTED_1000baseT_Full;
  162. if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
  163. result |= SUPPORTED_10000baseT_Full;
  164. if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
  165. result |= SUPPORTED_40000baseCR4_Full;
  166. break;
  167. case MC_CMD_MEDIA_BASE_T:
  168. result |= SUPPORTED_TP;
  169. if (cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
  170. result |= SUPPORTED_10baseT_Half;
  171. if (cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN))
  172. result |= SUPPORTED_10baseT_Full;
  173. if (cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN))
  174. result |= SUPPORTED_100baseT_Half;
  175. if (cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN))
  176. result |= SUPPORTED_100baseT_Full;
  177. if (cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN))
  178. result |= SUPPORTED_1000baseT_Half;
  179. if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
  180. result |= SUPPORTED_1000baseT_Full;
  181. if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
  182. result |= SUPPORTED_10000baseT_Full;
  183. break;
  184. }
  185. if (cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
  186. result |= SUPPORTED_Pause;
  187. if (cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
  188. result |= SUPPORTED_Asym_Pause;
  189. if (cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
  190. result |= SUPPORTED_Autoneg;
  191. return result;
  192. }
  193. static u32 ethtool_to_mcdi_cap(u32 cap)
  194. {
  195. u32 result = 0;
  196. if (cap & SUPPORTED_10baseT_Half)
  197. result |= (1 << MC_CMD_PHY_CAP_10HDX_LBN);
  198. if (cap & SUPPORTED_10baseT_Full)
  199. result |= (1 << MC_CMD_PHY_CAP_10FDX_LBN);
  200. if (cap & SUPPORTED_100baseT_Half)
  201. result |= (1 << MC_CMD_PHY_CAP_100HDX_LBN);
  202. if (cap & SUPPORTED_100baseT_Full)
  203. result |= (1 << MC_CMD_PHY_CAP_100FDX_LBN);
  204. if (cap & SUPPORTED_1000baseT_Half)
  205. result |= (1 << MC_CMD_PHY_CAP_1000HDX_LBN);
  206. if (cap & (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseKX_Full))
  207. result |= (1 << MC_CMD_PHY_CAP_1000FDX_LBN);
  208. if (cap & (SUPPORTED_10000baseT_Full | SUPPORTED_10000baseKX4_Full))
  209. result |= (1 << MC_CMD_PHY_CAP_10000FDX_LBN);
  210. if (cap & (SUPPORTED_40000baseCR4_Full | SUPPORTED_40000baseKR4_Full))
  211. result |= (1 << MC_CMD_PHY_CAP_40000FDX_LBN);
  212. if (cap & SUPPORTED_Pause)
  213. result |= (1 << MC_CMD_PHY_CAP_PAUSE_LBN);
  214. if (cap & SUPPORTED_Asym_Pause)
  215. result |= (1 << MC_CMD_PHY_CAP_ASYM_LBN);
  216. if (cap & SUPPORTED_Autoneg)
  217. result |= (1 << MC_CMD_PHY_CAP_AN_LBN);
  218. return result;
  219. }
  220. static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx)
  221. {
  222. struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
  223. enum efx_phy_mode mode, supported;
  224. u32 flags;
  225. /* TODO: Advertise the capabilities supported by this PHY */
  226. supported = 0;
  227. if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN))
  228. supported |= PHY_MODE_TX_DISABLED;
  229. if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN))
  230. supported |= PHY_MODE_LOW_POWER;
  231. if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN))
  232. supported |= PHY_MODE_OFF;
  233. mode = efx->phy_mode & supported;
  234. flags = 0;
  235. if (mode & PHY_MODE_TX_DISABLED)
  236. flags |= (1 << MC_CMD_SET_LINK_IN_TXDIS_LBN);
  237. if (mode & PHY_MODE_LOW_POWER)
  238. flags |= (1 << MC_CMD_SET_LINK_IN_LOWPOWER_LBN);
  239. if (mode & PHY_MODE_OFF)
  240. flags |= (1 << MC_CMD_SET_LINK_IN_POWEROFF_LBN);
  241. return flags;
  242. }
  243. static u32 mcdi_to_ethtool_media(u32 media)
  244. {
  245. switch (media) {
  246. case MC_CMD_MEDIA_XAUI:
  247. case MC_CMD_MEDIA_CX4:
  248. case MC_CMD_MEDIA_KX4:
  249. return PORT_OTHER;
  250. case MC_CMD_MEDIA_XFP:
  251. case MC_CMD_MEDIA_SFP_PLUS:
  252. case MC_CMD_MEDIA_QSFP_PLUS:
  253. return PORT_FIBRE;
  254. case MC_CMD_MEDIA_BASE_T:
  255. return PORT_TP;
  256. default:
  257. return PORT_OTHER;
  258. }
  259. }
  260. static void efx_mcdi_phy_decode_link(struct efx_nic *efx,
  261. struct efx_link_state *link_state,
  262. u32 speed, u32 flags, u32 fcntl)
  263. {
  264. switch (fcntl) {
  265. case MC_CMD_FCNTL_AUTO:
  266. WARN_ON(1); /* This is not a link mode */
  267. link_state->fc = EFX_FC_AUTO | EFX_FC_TX | EFX_FC_RX;
  268. break;
  269. case MC_CMD_FCNTL_BIDIR:
  270. link_state->fc = EFX_FC_TX | EFX_FC_RX;
  271. break;
  272. case MC_CMD_FCNTL_RESPOND:
  273. link_state->fc = EFX_FC_RX;
  274. break;
  275. default:
  276. WARN_ON(1);
  277. case MC_CMD_FCNTL_OFF:
  278. link_state->fc = 0;
  279. break;
  280. }
  281. link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
  282. link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
  283. link_state->speed = speed;
  284. }
  285. static int efx_mcdi_phy_probe(struct efx_nic *efx)
  286. {
  287. struct efx_mcdi_phy_data *phy_data;
  288. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
  289. u32 caps;
  290. int rc;
  291. /* Initialise and populate phy_data */
  292. phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
  293. if (phy_data == NULL)
  294. return -ENOMEM;
  295. rc = efx_mcdi_get_phy_cfg(efx, phy_data);
  296. if (rc != 0)
  297. goto fail;
  298. /* Read initial link advertisement */
  299. BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
  300. rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
  301. outbuf, sizeof(outbuf), NULL);
  302. if (rc)
  303. goto fail;
  304. /* Fill out nic state */
  305. efx->phy_data = phy_data;
  306. efx->phy_type = phy_data->type;
  307. efx->mdio_bus = phy_data->channel;
  308. efx->mdio.prtad = phy_data->port;
  309. efx->mdio.mmds = phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22);
  310. efx->mdio.mode_support = 0;
  311. if (phy_data->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22))
  312. efx->mdio.mode_support |= MDIO_SUPPORTS_C22;
  313. if (phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22))
  314. efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
  315. caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP);
  316. if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN))
  317. efx->link_advertising =
  318. mcdi_to_ethtool_cap(phy_data->media, caps);
  319. else
  320. phy_data->forced_cap = caps;
  321. /* Assert that we can map efx -> mcdi loopback modes */
  322. BUILD_BUG_ON(LOOPBACK_NONE != MC_CMD_LOOPBACK_NONE);
  323. BUILD_BUG_ON(LOOPBACK_DATA != MC_CMD_LOOPBACK_DATA);
  324. BUILD_BUG_ON(LOOPBACK_GMAC != MC_CMD_LOOPBACK_GMAC);
  325. BUILD_BUG_ON(LOOPBACK_XGMII != MC_CMD_LOOPBACK_XGMII);
  326. BUILD_BUG_ON(LOOPBACK_XGXS != MC_CMD_LOOPBACK_XGXS);
  327. BUILD_BUG_ON(LOOPBACK_XAUI != MC_CMD_LOOPBACK_XAUI);
  328. BUILD_BUG_ON(LOOPBACK_GMII != MC_CMD_LOOPBACK_GMII);
  329. BUILD_BUG_ON(LOOPBACK_SGMII != MC_CMD_LOOPBACK_SGMII);
  330. BUILD_BUG_ON(LOOPBACK_XGBR != MC_CMD_LOOPBACK_XGBR);
  331. BUILD_BUG_ON(LOOPBACK_XFI != MC_CMD_LOOPBACK_XFI);
  332. BUILD_BUG_ON(LOOPBACK_XAUI_FAR != MC_CMD_LOOPBACK_XAUI_FAR);
  333. BUILD_BUG_ON(LOOPBACK_GMII_FAR != MC_CMD_LOOPBACK_GMII_FAR);
  334. BUILD_BUG_ON(LOOPBACK_SGMII_FAR != MC_CMD_LOOPBACK_SGMII_FAR);
  335. BUILD_BUG_ON(LOOPBACK_XFI_FAR != MC_CMD_LOOPBACK_XFI_FAR);
  336. BUILD_BUG_ON(LOOPBACK_GPHY != MC_CMD_LOOPBACK_GPHY);
  337. BUILD_BUG_ON(LOOPBACK_PHYXS != MC_CMD_LOOPBACK_PHYXS);
  338. BUILD_BUG_ON(LOOPBACK_PCS != MC_CMD_LOOPBACK_PCS);
  339. BUILD_BUG_ON(LOOPBACK_PMAPMD != MC_CMD_LOOPBACK_PMAPMD);
  340. BUILD_BUG_ON(LOOPBACK_XPORT != MC_CMD_LOOPBACK_XPORT);
  341. BUILD_BUG_ON(LOOPBACK_XGMII_WS != MC_CMD_LOOPBACK_XGMII_WS);
  342. BUILD_BUG_ON(LOOPBACK_XAUI_WS != MC_CMD_LOOPBACK_XAUI_WS);
  343. BUILD_BUG_ON(LOOPBACK_XAUI_WS_FAR != MC_CMD_LOOPBACK_XAUI_WS_FAR);
  344. BUILD_BUG_ON(LOOPBACK_XAUI_WS_NEAR != MC_CMD_LOOPBACK_XAUI_WS_NEAR);
  345. BUILD_BUG_ON(LOOPBACK_GMII_WS != MC_CMD_LOOPBACK_GMII_WS);
  346. BUILD_BUG_ON(LOOPBACK_XFI_WS != MC_CMD_LOOPBACK_XFI_WS);
  347. BUILD_BUG_ON(LOOPBACK_XFI_WS_FAR != MC_CMD_LOOPBACK_XFI_WS_FAR);
  348. BUILD_BUG_ON(LOOPBACK_PHYXS_WS != MC_CMD_LOOPBACK_PHYXS_WS);
  349. rc = efx_mcdi_loopback_modes(efx, &efx->loopback_modes);
  350. if (rc != 0)
  351. goto fail;
  352. /* The MC indicates that LOOPBACK_NONE is a valid loopback mode,
  353. * but by convention we don't */
  354. efx->loopback_modes &= ~(1 << LOOPBACK_NONE);
  355. /* Set the initial link mode */
  356. efx_mcdi_phy_decode_link(
  357. efx, &efx->link_state,
  358. MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED),
  359. MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS),
  360. MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL));
  361. /* Default to Autonegotiated flow control if the PHY supports it */
  362. efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
  363. if (phy_data->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
  364. efx->wanted_fc |= EFX_FC_AUTO;
  365. efx_link_set_wanted_fc(efx, efx->wanted_fc);
  366. return 0;
  367. fail:
  368. kfree(phy_data);
  369. return rc;
  370. }
  371. int efx_mcdi_port_reconfigure(struct efx_nic *efx)
  372. {
  373. struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
  374. u32 caps = (efx->link_advertising ?
  375. ethtool_to_mcdi_cap(efx->link_advertising) :
  376. phy_cfg->forced_cap);
  377. return efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
  378. efx->loopback_mode, 0);
  379. }
  380. /* Verify that the forced flow control settings (!EFX_FC_AUTO) are
  381. * supported by the link partner. Warn the user if this isn't the case
  382. */
  383. static void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
  384. {
  385. struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
  386. u32 rmtadv;
  387. /* The link partner capabilities are only relevant if the
  388. * link supports flow control autonegotiation */
  389. if (~phy_cfg->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
  390. return;
  391. /* If flow control autoneg is supported and enabled, then fine */
  392. if (efx->wanted_fc & EFX_FC_AUTO)
  393. return;
  394. rmtadv = 0;
  395. if (lpa & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
  396. rmtadv |= ADVERTISED_Pause;
  397. if (lpa & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
  398. rmtadv |= ADVERTISED_Asym_Pause;
  399. if ((efx->wanted_fc & EFX_FC_TX) && rmtadv == ADVERTISED_Asym_Pause)
  400. netif_err(efx, link, efx->net_dev,
  401. "warning: link partner doesn't support pause frames");
  402. }
  403. static bool efx_mcdi_phy_poll(struct efx_nic *efx)
  404. {
  405. struct efx_link_state old_state = efx->link_state;
  406. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
  407. int rc;
  408. WARN_ON(!mutex_is_locked(&efx->mac_lock));
  409. BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
  410. rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
  411. outbuf, sizeof(outbuf), NULL);
  412. if (rc)
  413. efx->link_state.up = false;
  414. else
  415. efx_mcdi_phy_decode_link(
  416. efx, &efx->link_state,
  417. MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED),
  418. MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS),
  419. MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL));
  420. return !efx_link_state_equal(&efx->link_state, &old_state);
  421. }
  422. static void efx_mcdi_phy_remove(struct efx_nic *efx)
  423. {
  424. struct efx_mcdi_phy_data *phy_data = efx->phy_data;
  425. efx->phy_data = NULL;
  426. kfree(phy_data);
  427. }
  428. static void efx_mcdi_phy_get_link_ksettings(struct efx_nic *efx,
  429. struct ethtool_link_ksettings *cmd)
  430. {
  431. struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
  432. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
  433. int rc;
  434. u32 supported, advertising, lp_advertising;
  435. supported = mcdi_to_ethtool_cap(phy_cfg->media, phy_cfg->supported_cap);
  436. advertising = efx->link_advertising;
  437. cmd->base.speed = efx->link_state.speed;
  438. cmd->base.duplex = efx->link_state.fd;
  439. cmd->base.port = mcdi_to_ethtool_media(phy_cfg->media);
  440. cmd->base.phy_address = phy_cfg->port;
  441. cmd->base.autoneg = !!(efx->link_advertising & ADVERTISED_Autoneg);
  442. cmd->base.mdio_support = (efx->mdio.mode_support &
  443. (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22));
  444. ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
  445. supported);
  446. ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
  447. advertising);
  448. BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
  449. rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
  450. outbuf, sizeof(outbuf), NULL);
  451. if (rc)
  452. return;
  453. lp_advertising =
  454. mcdi_to_ethtool_cap(phy_cfg->media,
  455. MCDI_DWORD(outbuf, GET_LINK_OUT_LP_CAP));
  456. ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising,
  457. lp_advertising);
  458. }
  459. static int
  460. efx_mcdi_phy_set_link_ksettings(struct efx_nic *efx,
  461. const struct ethtool_link_ksettings *cmd)
  462. {
  463. struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
  464. u32 caps;
  465. int rc;
  466. u32 advertising;
  467. ethtool_convert_link_mode_to_legacy_u32(&advertising,
  468. cmd->link_modes.advertising);
  469. if (cmd->base.autoneg) {
  470. caps = (ethtool_to_mcdi_cap(advertising) |
  471. 1 << MC_CMD_PHY_CAP_AN_LBN);
  472. } else if (cmd->base.duplex) {
  473. switch (cmd->base.speed) {
  474. case 10: caps = 1 << MC_CMD_PHY_CAP_10FDX_LBN; break;
  475. case 100: caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN; break;
  476. case 1000: caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN; break;
  477. case 10000: caps = 1 << MC_CMD_PHY_CAP_10000FDX_LBN; break;
  478. case 40000: caps = 1 << MC_CMD_PHY_CAP_40000FDX_LBN; break;
  479. default: return -EINVAL;
  480. }
  481. } else {
  482. switch (cmd->base.speed) {
  483. case 10: caps = 1 << MC_CMD_PHY_CAP_10HDX_LBN; break;
  484. case 100: caps = 1 << MC_CMD_PHY_CAP_100HDX_LBN; break;
  485. case 1000: caps = 1 << MC_CMD_PHY_CAP_1000HDX_LBN; break;
  486. default: return -EINVAL;
  487. }
  488. }
  489. rc = efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
  490. efx->loopback_mode, 0);
  491. if (rc)
  492. return rc;
  493. if (cmd->base.autoneg) {
  494. efx_link_set_advertising(
  495. efx, advertising | ADVERTISED_Autoneg);
  496. phy_cfg->forced_cap = 0;
  497. } else {
  498. efx_link_set_advertising(efx, 0);
  499. phy_cfg->forced_cap = caps;
  500. }
  501. return 0;
  502. }
  503. static int efx_mcdi_phy_test_alive(struct efx_nic *efx)
  504. {
  505. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_STATE_OUT_LEN);
  506. size_t outlen;
  507. int rc;
  508. BUILD_BUG_ON(MC_CMD_GET_PHY_STATE_IN_LEN != 0);
  509. rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_STATE, NULL, 0,
  510. outbuf, sizeof(outbuf), &outlen);
  511. if (rc)
  512. return rc;
  513. if (outlen < MC_CMD_GET_PHY_STATE_OUT_LEN)
  514. return -EIO;
  515. if (MCDI_DWORD(outbuf, GET_PHY_STATE_OUT_STATE) != MC_CMD_PHY_STATE_OK)
  516. return -EINVAL;
  517. return 0;
  518. }
  519. static const char *const mcdi_sft9001_cable_diag_names[] = {
  520. "cable.pairA.length",
  521. "cable.pairB.length",
  522. "cable.pairC.length",
  523. "cable.pairD.length",
  524. "cable.pairA.status",
  525. "cable.pairB.status",
  526. "cable.pairC.status",
  527. "cable.pairD.status",
  528. };
  529. static int efx_mcdi_bist(struct efx_nic *efx, unsigned int bist_mode,
  530. int *results)
  531. {
  532. unsigned int retry, i, count = 0;
  533. size_t outlen;
  534. u32 status;
  535. MCDI_DECLARE_BUF(inbuf, MC_CMD_START_BIST_IN_LEN);
  536. MCDI_DECLARE_BUF(outbuf, MC_CMD_POLL_BIST_OUT_SFT9001_LEN);
  537. u8 *ptr;
  538. int rc;
  539. BUILD_BUG_ON(MC_CMD_START_BIST_OUT_LEN != 0);
  540. MCDI_SET_DWORD(inbuf, START_BIST_IN_TYPE, bist_mode);
  541. rc = efx_mcdi_rpc(efx, MC_CMD_START_BIST,
  542. inbuf, MC_CMD_START_BIST_IN_LEN, NULL, 0, NULL);
  543. if (rc)
  544. goto out;
  545. /* Wait up to 10s for BIST to finish */
  546. for (retry = 0; retry < 100; ++retry) {
  547. BUILD_BUG_ON(MC_CMD_POLL_BIST_IN_LEN != 0);
  548. rc = efx_mcdi_rpc(efx, MC_CMD_POLL_BIST, NULL, 0,
  549. outbuf, sizeof(outbuf), &outlen);
  550. if (rc)
  551. goto out;
  552. status = MCDI_DWORD(outbuf, POLL_BIST_OUT_RESULT);
  553. if (status != MC_CMD_POLL_BIST_RUNNING)
  554. goto finished;
  555. msleep(100);
  556. }
  557. rc = -ETIMEDOUT;
  558. goto out;
  559. finished:
  560. results[count++] = (status == MC_CMD_POLL_BIST_PASSED) ? 1 : -1;
  561. /* SFT9001 specific cable diagnostics output */
  562. if (efx->phy_type == PHY_TYPE_SFT9001B &&
  563. (bist_mode == MC_CMD_PHY_BIST_CABLE_SHORT ||
  564. bist_mode == MC_CMD_PHY_BIST_CABLE_LONG)) {
  565. ptr = MCDI_PTR(outbuf, POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A);
  566. if (status == MC_CMD_POLL_BIST_PASSED &&
  567. outlen >= MC_CMD_POLL_BIST_OUT_SFT9001_LEN) {
  568. for (i = 0; i < 8; i++) {
  569. results[count + i] =
  570. EFX_DWORD_FIELD(((efx_dword_t *)ptr)[i],
  571. EFX_DWORD_0);
  572. }
  573. }
  574. count += 8;
  575. }
  576. rc = count;
  577. out:
  578. return rc;
  579. }
  580. static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
  581. unsigned flags)
  582. {
  583. struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
  584. u32 mode;
  585. int rc;
  586. if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) {
  587. rc = efx_mcdi_bist(efx, MC_CMD_PHY_BIST, results);
  588. if (rc < 0)
  589. return rc;
  590. results += rc;
  591. }
  592. /* If we support both LONG and SHORT, then run each in response to
  593. * break or not. Otherwise, run the one we support */
  594. mode = 0;
  595. if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN)) {
  596. if ((flags & ETH_TEST_FL_OFFLINE) &&
  597. (phy_cfg->flags &
  598. (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN)))
  599. mode = MC_CMD_PHY_BIST_CABLE_LONG;
  600. else
  601. mode = MC_CMD_PHY_BIST_CABLE_SHORT;
  602. } else if (phy_cfg->flags &
  603. (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))
  604. mode = MC_CMD_PHY_BIST_CABLE_LONG;
  605. if (mode != 0) {
  606. rc = efx_mcdi_bist(efx, mode, results);
  607. if (rc < 0)
  608. return rc;
  609. results += rc;
  610. }
  611. return 0;
  612. }
  613. static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,
  614. unsigned int index)
  615. {
  616. struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
  617. if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) {
  618. if (index == 0)
  619. return "bist";
  620. --index;
  621. }
  622. if (phy_cfg->flags & ((1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN) |
  623. (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))) {
  624. if (index == 0)
  625. return "cable";
  626. --index;
  627. if (efx->phy_type == PHY_TYPE_SFT9001B) {
  628. if (index < ARRAY_SIZE(mcdi_sft9001_cable_diag_names))
  629. return mcdi_sft9001_cable_diag_names[index];
  630. index -= ARRAY_SIZE(mcdi_sft9001_cable_diag_names);
  631. }
  632. }
  633. return NULL;
  634. }
  635. #define SFP_PAGE_SIZE 128
  636. #define SFF_DIAG_TYPE_OFFSET 92
  637. #define SFF_DIAG_ADDR_CHANGE BIT(2)
  638. #define SFF_8079_NUM_PAGES 2
  639. #define SFF_8472_NUM_PAGES 4
  640. #define SFF_8436_NUM_PAGES 5
  641. #define SFF_DMT_LEVEL_OFFSET 94
  642. /** efx_mcdi_phy_get_module_eeprom_page() - Get a single page of module eeprom
  643. * @efx: NIC context
  644. * @page: EEPROM page number
  645. * @data: Destination data pointer
  646. * @offset: Offset in page to copy from in to data
  647. * @space: Space available in data
  648. *
  649. * Return:
  650. * >=0 - amount of data copied
  651. * <0 - error
  652. */
  653. static int efx_mcdi_phy_get_module_eeprom_page(struct efx_nic *efx,
  654. unsigned int page,
  655. u8 *data, ssize_t offset,
  656. ssize_t space)
  657. {
  658. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX);
  659. MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN);
  660. size_t outlen;
  661. unsigned int payload_len;
  662. unsigned int to_copy;
  663. int rc;
  664. if (offset > SFP_PAGE_SIZE)
  665. return -EINVAL;
  666. to_copy = min(space, SFP_PAGE_SIZE - offset);
  667. MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page);
  668. rc = efx_mcdi_rpc_quiet(efx, MC_CMD_GET_PHY_MEDIA_INFO,
  669. inbuf, sizeof(inbuf),
  670. outbuf, sizeof(outbuf),
  671. &outlen);
  672. if (rc)
  673. return rc;
  674. if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST +
  675. SFP_PAGE_SIZE))
  676. return -EIO;
  677. payload_len = MCDI_DWORD(outbuf, GET_PHY_MEDIA_INFO_OUT_DATALEN);
  678. if (payload_len != SFP_PAGE_SIZE)
  679. return -EIO;
  680. memcpy(data, MCDI_PTR(outbuf, GET_PHY_MEDIA_INFO_OUT_DATA) + offset,
  681. to_copy);
  682. return to_copy;
  683. }
  684. static int efx_mcdi_phy_get_module_eeprom_byte(struct efx_nic *efx,
  685. unsigned int page,
  686. u8 byte)
  687. {
  688. int rc;
  689. u8 data;
  690. rc = efx_mcdi_phy_get_module_eeprom_page(efx, page, &data, byte, 1);
  691. if (rc == 1)
  692. return data;
  693. return rc;
  694. }
  695. static int efx_mcdi_phy_diag_type(struct efx_nic *efx)
  696. {
  697. /* Page zero of the EEPROM includes the diagnostic type at byte 92. */
  698. return efx_mcdi_phy_get_module_eeprom_byte(efx, 0,
  699. SFF_DIAG_TYPE_OFFSET);
  700. }
  701. static int efx_mcdi_phy_sff_8472_level(struct efx_nic *efx)
  702. {
  703. /* Page zero of the EEPROM includes the DMT level at byte 94. */
  704. return efx_mcdi_phy_get_module_eeprom_byte(efx, 0,
  705. SFF_DMT_LEVEL_OFFSET);
  706. }
  707. static u32 efx_mcdi_phy_module_type(struct efx_nic *efx)
  708. {
  709. struct efx_mcdi_phy_data *phy_data = efx->phy_data;
  710. if (phy_data->media != MC_CMD_MEDIA_QSFP_PLUS)
  711. return phy_data->media;
  712. /* A QSFP+ NIC may actually have an SFP+ module attached.
  713. * The ID is page 0, byte 0.
  714. */
  715. switch (efx_mcdi_phy_get_module_eeprom_byte(efx, 0, 0)) {
  716. case 0x3:
  717. return MC_CMD_MEDIA_SFP_PLUS;
  718. case 0xc:
  719. case 0xd:
  720. return MC_CMD_MEDIA_QSFP_PLUS;
  721. default:
  722. return 0;
  723. }
  724. }
  725. static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx,
  726. struct ethtool_eeprom *ee, u8 *data)
  727. {
  728. int rc;
  729. ssize_t space_remaining = ee->len;
  730. unsigned int page_off;
  731. bool ignore_missing;
  732. int num_pages;
  733. int page;
  734. switch (efx_mcdi_phy_module_type(efx)) {
  735. case MC_CMD_MEDIA_SFP_PLUS:
  736. num_pages = efx_mcdi_phy_sff_8472_level(efx) > 0 ?
  737. SFF_8472_NUM_PAGES : SFF_8079_NUM_PAGES;
  738. page = 0;
  739. ignore_missing = false;
  740. break;
  741. case MC_CMD_MEDIA_QSFP_PLUS:
  742. num_pages = SFF_8436_NUM_PAGES;
  743. page = -1; /* We obtain the lower page by asking for -1. */
  744. ignore_missing = true; /* Ignore missing pages after page 0. */
  745. break;
  746. default:
  747. return -EOPNOTSUPP;
  748. }
  749. page_off = ee->offset % SFP_PAGE_SIZE;
  750. page += ee->offset / SFP_PAGE_SIZE;
  751. while (space_remaining && (page < num_pages)) {
  752. rc = efx_mcdi_phy_get_module_eeprom_page(efx, page,
  753. data, page_off,
  754. space_remaining);
  755. if (rc > 0) {
  756. space_remaining -= rc;
  757. data += rc;
  758. page_off = 0;
  759. page++;
  760. } else if (rc == 0) {
  761. space_remaining = 0;
  762. } else if (ignore_missing && (page > 0)) {
  763. int intended_size = SFP_PAGE_SIZE - page_off;
  764. space_remaining -= intended_size;
  765. if (space_remaining < 0) {
  766. space_remaining = 0;
  767. } else {
  768. memset(data, 0, intended_size);
  769. data += intended_size;
  770. page_off = 0;
  771. page++;
  772. rc = 0;
  773. }
  774. } else {
  775. return rc;
  776. }
  777. }
  778. return 0;
  779. }
  780. static int efx_mcdi_phy_get_module_info(struct efx_nic *efx,
  781. struct ethtool_modinfo *modinfo)
  782. {
  783. int sff_8472_level;
  784. int diag_type;
  785. switch (efx_mcdi_phy_module_type(efx)) {
  786. case MC_CMD_MEDIA_SFP_PLUS:
  787. sff_8472_level = efx_mcdi_phy_sff_8472_level(efx);
  788. /* If we can't read the diagnostics level we have none. */
  789. if (sff_8472_level < 0)
  790. return -EOPNOTSUPP;
  791. /* Check if this module requires the (unsupported) address
  792. * change operation.
  793. */
  794. diag_type = efx_mcdi_phy_diag_type(efx);
  795. if ((sff_8472_level == 0) ||
  796. (diag_type & SFF_DIAG_ADDR_CHANGE)) {
  797. modinfo->type = ETH_MODULE_SFF_8079;
  798. modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
  799. } else {
  800. modinfo->type = ETH_MODULE_SFF_8472;
  801. modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
  802. }
  803. break;
  804. case MC_CMD_MEDIA_QSFP_PLUS:
  805. modinfo->type = ETH_MODULE_SFF_8436;
  806. modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
  807. break;
  808. default:
  809. return -EOPNOTSUPP;
  810. }
  811. return 0;
  812. }
  813. static const struct efx_phy_operations efx_mcdi_phy_ops = {
  814. .probe = efx_mcdi_phy_probe,
  815. .init = efx_port_dummy_op_int,
  816. .reconfigure = efx_mcdi_port_reconfigure,
  817. .poll = efx_mcdi_phy_poll,
  818. .fini = efx_port_dummy_op_void,
  819. .remove = efx_mcdi_phy_remove,
  820. .get_link_ksettings = efx_mcdi_phy_get_link_ksettings,
  821. .set_link_ksettings = efx_mcdi_phy_set_link_ksettings,
  822. .test_alive = efx_mcdi_phy_test_alive,
  823. .run_tests = efx_mcdi_phy_run_tests,
  824. .test_name = efx_mcdi_phy_test_name,
  825. .get_module_eeprom = efx_mcdi_phy_get_module_eeprom,
  826. .get_module_info = efx_mcdi_phy_get_module_info,
  827. };
  828. u32 efx_mcdi_phy_get_caps(struct efx_nic *efx)
  829. {
  830. struct efx_mcdi_phy_data *phy_data = efx->phy_data;
  831. return phy_data->supported_cap;
  832. }
  833. static unsigned int efx_mcdi_event_link_speed[] = {
  834. [MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
  835. [MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
  836. [MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000,
  837. [MCDI_EVENT_LINKCHANGE_SPEED_40G] = 40000,
  838. };
  839. void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
  840. {
  841. u32 flags, fcntl, speed, lpa;
  842. speed = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_SPEED);
  843. EFX_WARN_ON_PARANOID(speed >= ARRAY_SIZE(efx_mcdi_event_link_speed));
  844. speed = efx_mcdi_event_link_speed[speed];
  845. flags = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LINK_FLAGS);
  846. fcntl = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_FCNTL);
  847. lpa = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LP_CAP);
  848. /* efx->link_state is only modified by efx_mcdi_phy_get_link(),
  849. * which is only run after flushing the event queues. Therefore, it
  850. * is safe to modify the link state outside of the mac_lock here.
  851. */
  852. efx_mcdi_phy_decode_link(efx, &efx->link_state, speed, flags, fcntl);
  853. efx_mcdi_phy_check_fcntl(efx, lpa);
  854. efx_link_status_changed(efx);
  855. }
  856. int efx_mcdi_set_mac(struct efx_nic *efx)
  857. {
  858. u32 fcntl;
  859. MCDI_DECLARE_BUF(cmdbytes, MC_CMD_SET_MAC_IN_LEN);
  860. BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0);
  861. /* This has no effect on EF10 */
  862. ether_addr_copy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR),
  863. efx->net_dev->dev_addr);
  864. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU,
  865. EFX_MAX_FRAME_LEN(efx->net_dev->mtu));
  866. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0);
  867. /* Set simple MAC filter for Siena */
  868. MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_REJECT,
  869. SET_MAC_IN_REJECT_UNCST, efx->unicast_filter);
  870. switch (efx->wanted_fc) {
  871. case EFX_FC_RX | EFX_FC_TX:
  872. fcntl = MC_CMD_FCNTL_BIDIR;
  873. break;
  874. case EFX_FC_RX:
  875. fcntl = MC_CMD_FCNTL_RESPOND;
  876. break;
  877. default:
  878. fcntl = MC_CMD_FCNTL_OFF;
  879. break;
  880. }
  881. if (efx->wanted_fc & EFX_FC_AUTO)
  882. fcntl = MC_CMD_FCNTL_AUTO;
  883. if (efx->fc_disable)
  884. fcntl = MC_CMD_FCNTL_OFF;
  885. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
  886. return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes),
  887. NULL, 0, NULL);
  888. }
  889. bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
  890. {
  891. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
  892. size_t outlength;
  893. int rc;
  894. BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
  895. rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
  896. outbuf, sizeof(outbuf), &outlength);
  897. if (rc)
  898. return true;
  899. return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
  900. }
  901. enum efx_stats_action {
  902. EFX_STATS_ENABLE,
  903. EFX_STATS_DISABLE,
  904. EFX_STATS_PULL,
  905. };
  906. static int efx_mcdi_mac_stats(struct efx_nic *efx,
  907. enum efx_stats_action action, int clear)
  908. {
  909. MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
  910. int rc;
  911. int change = action == EFX_STATS_PULL ? 0 : 1;
  912. int enable = action == EFX_STATS_ENABLE ? 1 : 0;
  913. int period = action == EFX_STATS_ENABLE ? 1000 : 0;
  914. dma_addr_t dma_addr = efx->stats_buffer.dma_addr;
  915. u32 dma_len = action != EFX_STATS_DISABLE ?
  916. MC_CMD_MAC_NSTATS * sizeof(u64) : 0;
  917. BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);
  918. MCDI_SET_QWORD(inbuf, MAC_STATS_IN_DMA_ADDR, dma_addr);
  919. MCDI_POPULATE_DWORD_7(inbuf, MAC_STATS_IN_CMD,
  920. MAC_STATS_IN_DMA, !!enable,
  921. MAC_STATS_IN_CLEAR, clear,
  922. MAC_STATS_IN_PERIODIC_CHANGE, change,
  923. MAC_STATS_IN_PERIODIC_ENABLE, enable,
  924. MAC_STATS_IN_PERIODIC_CLEAR, 0,
  925. MAC_STATS_IN_PERIODIC_NOEVENT, 1,
  926. MAC_STATS_IN_PERIOD_MS, period);
  927. MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
  928. if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
  929. struct efx_ef10_nic_data *nic_data = efx->nic_data;
  930. MCDI_SET_DWORD(inbuf, MAC_STATS_IN_PORT_ID, nic_data->vport_id);
  931. }
  932. rc = efx_mcdi_rpc_quiet(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
  933. NULL, 0, NULL);
  934. /* Expect ENOENT if DMA queues have not been set up */
  935. if (rc && (rc != -ENOENT || atomic_read(&efx->active_queues)))
  936. efx_mcdi_display_error(efx, MC_CMD_MAC_STATS, sizeof(inbuf),
  937. NULL, 0, rc);
  938. return rc;
  939. }
  940. void efx_mcdi_mac_start_stats(struct efx_nic *efx)
  941. {
  942. __le64 *dma_stats = efx->stats_buffer.addr;
  943. dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
  944. efx_mcdi_mac_stats(efx, EFX_STATS_ENABLE, 0);
  945. }
  946. void efx_mcdi_mac_stop_stats(struct efx_nic *efx)
  947. {
  948. efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 0);
  949. }
  950. #define EFX_MAC_STATS_WAIT_US 100
  951. #define EFX_MAC_STATS_WAIT_ATTEMPTS 10
  952. void efx_mcdi_mac_pull_stats(struct efx_nic *efx)
  953. {
  954. __le64 *dma_stats = efx->stats_buffer.addr;
  955. int attempts = EFX_MAC_STATS_WAIT_ATTEMPTS;
  956. dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
  957. efx_mcdi_mac_stats(efx, EFX_STATS_PULL, 0);
  958. while (dma_stats[MC_CMD_MAC_GENERATION_END] ==
  959. EFX_MC_STATS_GENERATION_INVALID &&
  960. attempts-- != 0)
  961. udelay(EFX_MAC_STATS_WAIT_US);
  962. }
  963. int efx_mcdi_port_probe(struct efx_nic *efx)
  964. {
  965. int rc;
  966. /* Hook in PHY operations table */
  967. efx->phy_op = &efx_mcdi_phy_ops;
  968. /* Set up MDIO structure for PHY */
  969. efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
  970. efx->mdio.mdio_read = efx_mcdi_mdio_read;
  971. efx->mdio.mdio_write = efx_mcdi_mdio_write;
  972. /* Fill out MDIO structure, loopback modes, and initial link state */
  973. rc = efx->phy_op->probe(efx);
  974. if (rc != 0)
  975. return rc;
  976. /* Allocate buffer for stats */
  977. rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
  978. MC_CMD_MAC_NSTATS * sizeof(u64), GFP_KERNEL);
  979. if (rc)
  980. return rc;
  981. netif_dbg(efx, probe, efx->net_dev,
  982. "stats buffer at %llx (virt %p phys %llx)\n",
  983. (u64)efx->stats_buffer.dma_addr,
  984. efx->stats_buffer.addr,
  985. (u64)virt_to_phys(efx->stats_buffer.addr));
  986. efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 1);
  987. return 0;
  988. }
  989. void efx_mcdi_port_remove(struct efx_nic *efx)
  990. {
  991. efx->phy_op->remove(efx);
  992. efx_nic_free_buffer(efx, &efx->stats_buffer);
  993. }
  994. /* Get physical port number (EF10 only; on Siena it is same as PF number) */
  995. int efx_mcdi_port_get_number(struct efx_nic *efx)
  996. {
  997. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
  998. int rc;
  999. rc = efx_mcdi_rpc(efx, MC_CMD_GET_PORT_ASSIGNMENT, NULL, 0,
  1000. outbuf, sizeof(outbuf), NULL);
  1001. if (rc)
  1002. return rc;
  1003. return MCDI_DWORD(outbuf, GET_PORT_ASSIGNMENT_OUT_PORT);
  1004. }