mcdi_port.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  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 SFP_NUM_PAGES 2
  637. static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx,
  638. struct ethtool_eeprom *ee, u8 *data)
  639. {
  640. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX);
  641. MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN);
  642. size_t outlen;
  643. int rc;
  644. unsigned int payload_len;
  645. unsigned int space_remaining = ee->len;
  646. unsigned int page;
  647. unsigned int page_off;
  648. unsigned int to_copy;
  649. u8 *user_data = data;
  650. BUILD_BUG_ON(SFP_PAGE_SIZE * SFP_NUM_PAGES != ETH_MODULE_SFF_8079_LEN);
  651. page_off = ee->offset % SFP_PAGE_SIZE;
  652. page = ee->offset / SFP_PAGE_SIZE;
  653. while (space_remaining && (page < SFP_NUM_PAGES)) {
  654. MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page);
  655. rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_MEDIA_INFO,
  656. inbuf, sizeof(inbuf),
  657. outbuf, sizeof(outbuf),
  658. &outlen);
  659. if (rc)
  660. return rc;
  661. if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST +
  662. SFP_PAGE_SIZE))
  663. return -EIO;
  664. payload_len = MCDI_DWORD(outbuf,
  665. GET_PHY_MEDIA_INFO_OUT_DATALEN);
  666. if (payload_len != SFP_PAGE_SIZE)
  667. return -EIO;
  668. /* Copy as much as we can into data */
  669. payload_len -= page_off;
  670. to_copy = (space_remaining < payload_len) ?
  671. space_remaining : payload_len;
  672. memcpy(user_data,
  673. MCDI_PTR(outbuf, GET_PHY_MEDIA_INFO_OUT_DATA) + page_off,
  674. to_copy);
  675. space_remaining -= to_copy;
  676. user_data += to_copy;
  677. page_off = 0;
  678. page++;
  679. }
  680. return 0;
  681. }
  682. static int efx_mcdi_phy_get_module_info(struct efx_nic *efx,
  683. struct ethtool_modinfo *modinfo)
  684. {
  685. struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
  686. switch (phy_cfg->media) {
  687. case MC_CMD_MEDIA_SFP_PLUS:
  688. modinfo->type = ETH_MODULE_SFF_8079;
  689. modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
  690. return 0;
  691. default:
  692. return -EOPNOTSUPP;
  693. }
  694. }
  695. static const struct efx_phy_operations efx_mcdi_phy_ops = {
  696. .probe = efx_mcdi_phy_probe,
  697. .init = efx_port_dummy_op_int,
  698. .reconfigure = efx_mcdi_port_reconfigure,
  699. .poll = efx_mcdi_phy_poll,
  700. .fini = efx_port_dummy_op_void,
  701. .remove = efx_mcdi_phy_remove,
  702. .get_link_ksettings = efx_mcdi_phy_get_link_ksettings,
  703. .set_link_ksettings = efx_mcdi_phy_set_link_ksettings,
  704. .test_alive = efx_mcdi_phy_test_alive,
  705. .run_tests = efx_mcdi_phy_run_tests,
  706. .test_name = efx_mcdi_phy_test_name,
  707. .get_module_eeprom = efx_mcdi_phy_get_module_eeprom,
  708. .get_module_info = efx_mcdi_phy_get_module_info,
  709. };
  710. u32 efx_mcdi_phy_get_caps(struct efx_nic *efx)
  711. {
  712. struct efx_mcdi_phy_data *phy_data = efx->phy_data;
  713. return phy_data->supported_cap;
  714. }
  715. static unsigned int efx_mcdi_event_link_speed[] = {
  716. [MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
  717. [MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
  718. [MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000,
  719. [MCDI_EVENT_LINKCHANGE_SPEED_40G] = 40000,
  720. };
  721. void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
  722. {
  723. u32 flags, fcntl, speed, lpa;
  724. speed = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_SPEED);
  725. EFX_WARN_ON_PARANOID(speed >= ARRAY_SIZE(efx_mcdi_event_link_speed));
  726. speed = efx_mcdi_event_link_speed[speed];
  727. flags = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LINK_FLAGS);
  728. fcntl = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_FCNTL);
  729. lpa = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LP_CAP);
  730. /* efx->link_state is only modified by efx_mcdi_phy_get_link(),
  731. * which is only run after flushing the event queues. Therefore, it
  732. * is safe to modify the link state outside of the mac_lock here.
  733. */
  734. efx_mcdi_phy_decode_link(efx, &efx->link_state, speed, flags, fcntl);
  735. efx_mcdi_phy_check_fcntl(efx, lpa);
  736. efx_link_status_changed(efx);
  737. }
  738. int efx_mcdi_set_mac(struct efx_nic *efx)
  739. {
  740. u32 fcntl;
  741. MCDI_DECLARE_BUF(cmdbytes, MC_CMD_SET_MAC_IN_LEN);
  742. BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0);
  743. /* This has no effect on EF10 */
  744. ether_addr_copy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR),
  745. efx->net_dev->dev_addr);
  746. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU,
  747. EFX_MAX_FRAME_LEN(efx->net_dev->mtu));
  748. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0);
  749. /* Set simple MAC filter for Siena */
  750. MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_REJECT,
  751. SET_MAC_IN_REJECT_UNCST, efx->unicast_filter);
  752. switch (efx->wanted_fc) {
  753. case EFX_FC_RX | EFX_FC_TX:
  754. fcntl = MC_CMD_FCNTL_BIDIR;
  755. break;
  756. case EFX_FC_RX:
  757. fcntl = MC_CMD_FCNTL_RESPOND;
  758. break;
  759. default:
  760. fcntl = MC_CMD_FCNTL_OFF;
  761. break;
  762. }
  763. if (efx->wanted_fc & EFX_FC_AUTO)
  764. fcntl = MC_CMD_FCNTL_AUTO;
  765. if (efx->fc_disable)
  766. fcntl = MC_CMD_FCNTL_OFF;
  767. MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
  768. return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes),
  769. NULL, 0, NULL);
  770. }
  771. bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
  772. {
  773. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
  774. size_t outlength;
  775. int rc;
  776. BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
  777. rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
  778. outbuf, sizeof(outbuf), &outlength);
  779. if (rc)
  780. return true;
  781. return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
  782. }
  783. enum efx_stats_action {
  784. EFX_STATS_ENABLE,
  785. EFX_STATS_DISABLE,
  786. EFX_STATS_PULL,
  787. };
  788. static int efx_mcdi_mac_stats(struct efx_nic *efx,
  789. enum efx_stats_action action, int clear)
  790. {
  791. struct efx_ef10_nic_data *nic_data = efx->nic_data;
  792. MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
  793. int rc;
  794. int change = action == EFX_STATS_PULL ? 0 : 1;
  795. int enable = action == EFX_STATS_ENABLE ? 1 : 0;
  796. int period = action == EFX_STATS_ENABLE ? 1000 : 0;
  797. dma_addr_t dma_addr = efx->stats_buffer.dma_addr;
  798. u32 dma_len = action != EFX_STATS_DISABLE ?
  799. MC_CMD_MAC_NSTATS * sizeof(u64) : 0;
  800. BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);
  801. MCDI_SET_QWORD(inbuf, MAC_STATS_IN_DMA_ADDR, dma_addr);
  802. MCDI_POPULATE_DWORD_7(inbuf, MAC_STATS_IN_CMD,
  803. MAC_STATS_IN_DMA, !!enable,
  804. MAC_STATS_IN_CLEAR, clear,
  805. MAC_STATS_IN_PERIODIC_CHANGE, change,
  806. MAC_STATS_IN_PERIODIC_ENABLE, enable,
  807. MAC_STATS_IN_PERIODIC_CLEAR, 0,
  808. MAC_STATS_IN_PERIODIC_NOEVENT, 1,
  809. MAC_STATS_IN_PERIOD_MS, period);
  810. MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
  811. MCDI_SET_DWORD(inbuf, MAC_STATS_IN_PORT_ID, nic_data->vport_id);
  812. rc = efx_mcdi_rpc_quiet(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
  813. NULL, 0, NULL);
  814. /* Expect ENOENT if DMA queues have not been set up */
  815. if (rc && (rc != -ENOENT || atomic_read(&efx->active_queues)))
  816. efx_mcdi_display_error(efx, MC_CMD_MAC_STATS, sizeof(inbuf),
  817. NULL, 0, rc);
  818. return rc;
  819. }
  820. void efx_mcdi_mac_start_stats(struct efx_nic *efx)
  821. {
  822. __le64 *dma_stats = efx->stats_buffer.addr;
  823. dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
  824. efx_mcdi_mac_stats(efx, EFX_STATS_ENABLE, 0);
  825. }
  826. void efx_mcdi_mac_stop_stats(struct efx_nic *efx)
  827. {
  828. efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 0);
  829. }
  830. #define EFX_MAC_STATS_WAIT_US 100
  831. #define EFX_MAC_STATS_WAIT_ATTEMPTS 10
  832. void efx_mcdi_mac_pull_stats(struct efx_nic *efx)
  833. {
  834. __le64 *dma_stats = efx->stats_buffer.addr;
  835. int attempts = EFX_MAC_STATS_WAIT_ATTEMPTS;
  836. dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
  837. efx_mcdi_mac_stats(efx, EFX_STATS_PULL, 0);
  838. while (dma_stats[MC_CMD_MAC_GENERATION_END] ==
  839. EFX_MC_STATS_GENERATION_INVALID &&
  840. attempts-- != 0)
  841. udelay(EFX_MAC_STATS_WAIT_US);
  842. }
  843. int efx_mcdi_port_probe(struct efx_nic *efx)
  844. {
  845. int rc;
  846. /* Hook in PHY operations table */
  847. efx->phy_op = &efx_mcdi_phy_ops;
  848. /* Set up MDIO structure for PHY */
  849. efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
  850. efx->mdio.mdio_read = efx_mcdi_mdio_read;
  851. efx->mdio.mdio_write = efx_mcdi_mdio_write;
  852. /* Fill out MDIO structure, loopback modes, and initial link state */
  853. rc = efx->phy_op->probe(efx);
  854. if (rc != 0)
  855. return rc;
  856. /* Allocate buffer for stats */
  857. rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
  858. MC_CMD_MAC_NSTATS * sizeof(u64), GFP_KERNEL);
  859. if (rc)
  860. return rc;
  861. netif_dbg(efx, probe, efx->net_dev,
  862. "stats buffer at %llx (virt %p phys %llx)\n",
  863. (u64)efx->stats_buffer.dma_addr,
  864. efx->stats_buffer.addr,
  865. (u64)virt_to_phys(efx->stats_buffer.addr));
  866. efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 1);
  867. return 0;
  868. }
  869. void efx_mcdi_port_remove(struct efx_nic *efx)
  870. {
  871. efx->phy_op->remove(efx);
  872. efx_nic_free_buffer(efx, &efx->stats_buffer);
  873. }
  874. /* Get physical port number (EF10 only; on Siena it is same as PF number) */
  875. int efx_mcdi_port_get_number(struct efx_nic *efx)
  876. {
  877. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
  878. int rc;
  879. rc = efx_mcdi_rpc(efx, MC_CMD_GET_PORT_ASSIGNMENT, NULL, 0,
  880. outbuf, sizeof(outbuf), NULL);
  881. if (rc)
  882. return rc;
  883. return MCDI_DWORD(outbuf, GET_PORT_ASSIGNMENT_OUT_PORT);
  884. }